Remove pragmas introduced unnecessarily to "fix" r21707.

[Reviewed by hildeth.]

This undoes part of what I committed in r21727, to fix the compiler
internal errors caused by r21707.  Specifically, it removes the "insert
line file info" pragmas.  It turns out that those are not required.  The
change to the primitive definition to force the presence of line and
file arguments on the calls was all that was needed.

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@21731 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

// ChapelLocale.chpl
//
pragma "no use ChapelStandard"
module ChapelLocale {

  //
  // An abstract class. Specifies the required locale interface.
  // Each locale implementation must inherit from this class.
  //
  class locale {
    //- Constructor
    proc locale() {
// Now we find we have to create locales early, so _here can be non-nil.
      // compilerError("cannot create instances of the 'locale' class");
    }

    //------------------------------------------------------------------------{
    //- Fields and accessors defined for all locale types (not overridable)
    //-

    // Every locale has a parent, except for the root locale.
    // The parent of the root locale is nil (by definition).
    const parent : locale;

    // To be removed from the required interface once legacy code is adjusted.
    const numCores: int;

    // In legacy code, the id accessor is used to obtain the node id, so it
    // should probably be renamed as node_id.
    // As an accessor, it is statically bound, which is also a problem....
    proc id : int return chpl_id();
    proc name return chpl_name();
    //------------------------------------------------------------------------}

    //------------------------------------------------------------------------{
    //- User Interface Methods (overridable)
    //-

    // Returns a globally unique locale identifier.
    // This routine is dynamically dispatched, so it can be overridden in concrete classes.
    proc chpl_id() : int {
      _throwPVFCError();
      return -1;
    }

    proc chpl_name() : string {
      _throwPVFCError();
      return "";
    }

    // A useful default definition is provided (not pure virtual).
    proc readWriteThis(f) {
      f <~> name;
    }

    proc getChildCount() : int {
      _throwPVFCError();
      return 0;
    }

// Part of the required locale interface.
// Commented out because presently iterators are statically bound.
//    iter getChildIndices() : int {
//      for idx in this.getChildSpace do
//        yield idx;
//    }

    proc addChild(loc:locale)
    {
      _throwPVFCError();
    }

    proc getChild(idx:int) : locale {
      _throwPVFCError();
      return this;
    }

// Part of the required locale interface.
// Commented out because presently iterators are statically bound.
//    iter getChildren() : locale  {
//    _throwPVFCError();
//      yield 0;
//    }

    //------------------------------------------------------------------------}

    //------------------------------------------------------------------------{
    //- Compiler Interface Methods (overridable)
    //-

    // Part of the required locale interface.
    // These routines are called by the compiler to implement locale-aware task control.
    // They should be overridden in concrete locale classes as necessary.
    proc taskInit() : void {}
    proc taskExit() : void {}

    proc alloc(nbytes:int) {
      extern proc chpl_malloc(nbytes:int) : opaque;
      return chpl_malloc(nbytes);
    }

    proc calloc(count:int, nbytes:int) {
      extern proc chpl_calloc(count:int, nbytes:int) : opaque;
      return chpl_calloc(count, nbytes);
    }

    proc realloc(x:object, nbytes:int) {
      extern proc chpl_realloc(x:object, nbytes:int) : opaque;
      return chpl_realloc(x, nbytes);
    }

    proc free(x:object) {
      extern proc chpl_free(x:object) : void;
      chpl_free(x);
    }
    //------------------------------------------------------------------------}
  }

  class AbstractLocaleModel : locale {
    // This will be used for interfaces that will be common to all
    // (non-RootLocale) locale models
  }

  // rootLocale is declared to be of type locale rather than
  // RootLocale because doing so would make locales depend on arrays
  // which depend on locales, etc.
  //
  // If we had a way to express domain and array return types abstractly,
  // that problem would go away. <hilde>
  //
  // The rootLocale is private to each locale.  It cannot be
  // initialized until LocaleModel is initialized.  To disable this
  // replication, set replicateRootLocale to false.
  pragma "private" var rootLocale : locale = nil;
  config param replicateRootLocale = true;

  // The rootLocale needs to be initalized on all locales prior to
  // initializing the Locales array.  Unfortunately, the rootLocale
  // cannot be properly replicated until DefaultRectangular can be
  // initialized (as the private copies of the defaultDist are
  // needed).  We remedy this by initializing a rootLocale on locale 0
  // (called origRootLocale), and setting all locales' rootLocale to
  // origRootLocale.  Later, after DefaultRectangular can be
  // initialized, we create local copies of the rootLocale (and the
  // Locales array).  This is being done in the InitPrivateGlobals
  // module.
  //
  var origRootLocale : locale = nil;

  class AbstractRootLocale : locale {
    // These functions are used to establish values for Locales[] and
    // LocaleSpace -- an array of locales and its correponding domain
    // which are used as the default set of targetLocales in many
    // distributions.
    proc getDefaultLocaleSpace() {
      _throwPVFCError();
      const emptyLocaleSpace: domain(1) = {1..0};
      return emptyLocaleSpace;
    }

    proc getDefaultLocaleArray() {
      _throwPVFCError();
      const emptyLocaleSpace: domain(1) = {1..0};
      const emptyLocales: [emptyLocaleSpace] locale;
      return emptyLocales;
    }

    proc localeIDtoLocale(id : chpl_localeID_t) : locale {
      _throwPVFCError();
      return this;
    }

    // These iterators are to be used by RootLocale:init() to
    // initialize the LocaleModel.  The calling loop body cannot
    // contain any non-local code, since the rootLocale is not yet
    // initialized.
    iter initOnLocales() {
      if numLocales > 1 then
        halt("The locales must be initialized in parallel");
      for locIdx in (origRootLocale:RootLocale).getDefaultLocaleSpace() {
        yield locIdx;
        rootLocale = origRootLocale;
      }
    }

    iter initOnLocales(param tag: iterKind)
      where tag==iterKind.leader {
      for locIdx in (origRootLocale:RootLocale).getDefaultLocaleSpace() {
        var locID = chpl_buildLocaleID(locIdx:chpl_nodeID_t, 0:chpl_sublocID_t);
        // sublocale part of locID needs to be any
        on __primitive("chpl_on_locale_num", locID) {
          yield locIdx;
          rootLocale = origRootLocale;
        }
      }
    }

    iter initOnLocales(param tag: iterKind, followThis)
      where tag==iterKind.follower {
      yield followThis;
    }
  }

  // This function is called in the LocalesArray module to initialize
  // the rootLocale.  It sets up the origRootLocale and also includes
  // set up of the each locale's LocaleModel via DefaulRootLocale:init().
  //
  // The init() function must use chpl_rootLocale_locales() to iterate
  // (in parallel) over the locales to set up the LocaleModel object.
  // In addition, the initial 'here' must be set.
  //
  proc chpl_init_rootLocale() {
    origRootLocale = new RootLocale();

    (origRootLocale:RootLocale).init();

    // Programs traditionally expect the startup process to run on
    // Locales[0], so this is how we mimic that behavior.
    // Note that this means we have to ask for here.parent or rootLocale
    // to get the root locale of the default architecture.
    var loc = (origRootLocale:RootLocale).getDefaultLocaleArray()[0];
    __primitive("_task_set_here_ptr", loc);
    var locID = chpl_buildLocaleID(0:chpl_nodeID_t, 0:chpl_sublocID_t);
    __primitive("_task_set_locale_id", locID);
  }

  // This function sets up a private copy of rootLocale by replicating
  // origRootLocale and resets the Locales array to point to the local
  // copy.  It should be called on every locale except locale 0 after
  // it is safe to do so (after defaultDist is initialized).
  proc chpl_rootLocaleInitPrivate() {
    if !replicateRootLocale then return;
    // set rootLocale to a local copy
    var newRootLocale = new RootLocale();
    newRootLocale.getDefaultLocaleArray() =
      (origRootLocale:RootLocale).getDefaultLocaleArray();
    rootLocale = newRootLocale;
    // We mimic a private Locales array alias by using the move
    // primitive.  Note that this leaks the original local Locales
    // array wrapper.
    __primitive("move", Locales, (rootLocale:RootLocale).getDefaultLocaleArray());
  }

  // Returns a wide pointer to the locale with the given id.
  proc chpl_localeID_to_locale(id : chpl_localeID_t) : locale {
    if rootLocale then
      return (rootLocale:AbstractRootLocale).localeIDtoLocale(id);
    else
      // For code prior to rootLocale initialization
      return here;
  }

  // This returns the current "here" pointer.
  // It uses a primitive to suck the here pointer out of task-private storage.
  // On local builds, the primitive returns a narrow pointer;
  // otherwise, a wide pointer.
  //
  // Perhaps we can move this into the compiler as a special keyword....
  inline proc here return __primitive("_task_get_here_ptr");

  // We need a temporary value for "here" before the architecture is defined.
  // This is due to the fact that "here" is used for memory and task control
  // in setting up the architecture itself.
  // Its type should probably be renamed dummyLocale or something representative.
  // The dummy locale provides system-default tasking and memory management.
  __primitive("_task_set_here_ptr", new locale());

  pragma "insert line file info"
  extern proc chpl_memhook_malloc_pre(number:int, size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_malloc_post(ptr:opaque, number:int,
                                       size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_realloc_pre(ptr:object, size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_realloc_post(newPtr:opaque, ptr:object,
                                        size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_free_pre(ptr:opaque): void;
  extern proc chpl_memhook_md_num(): int(16);

  // Here be dragons: If the return type is specified, then normalize.cpp inserts
  // an initializer for the return value which calls its constructor, which calls
  // chpl_here_alloc ad infinitum.  But if the return type is left off, it works!

  // The allocator pragma is used by scalar replacement.
  pragma "allocator"
  pragma "no sync demotion"
  proc chpl_here_alloc(x, md:int(16)) {
    var nbytes = __primitive("sizeof", x);
    chpl_memhook_malloc_pre(1, nbytes, md + chpl_memhook_md_num());
    var mem = __primitive("task_alloc", nbytes);
    chpl_memhook_malloc_post(mem, 1, nbytes, md + chpl_memhook_md_num());
    return __primitive("cast", x.type, mem);
  }

  pragma "allocator"
  pragma "no sync demotion"
  proc chpl_here_calloc(x, number:int, md:int(16)) {
    extern proc chpl_task_calloc(number:int, nbytes:int) : opaque;
    var nbytes = __primitive("sizeof", x);
    chpl_memhook_malloc_pre(number, nbytes, md + chpl_memhook_md_num());
    var mem = chpl_task_calloc(number, nbytes);
    chpl_memhook_malloc_post(mem, number, nbytes, md + chpl_memhook_md_num());
    return __primitive("cast", x.type, mem);
  }

  pragma "allocator"
  pragma "no sync demotion"
  proc chpl_here_realloc(x, md:int(16)) {
    var nbytes = __primitive("sizeof", x);
    chpl_memhook_realloc_pre(x, nbytes, md + chpl_memhook_md_num());
    var mem = __primitive("task_realloc", x:object, nbytes);
    chpl_memhook_realloc_post(mem, x, nbytes, md + chpl_memhook_md_num());
    return __primitive("cast", x.type, mem);
  }

  pragma "no sync demotion"
  proc chpl_here_free(x) {
    // TODO: The pointer should really be of type opaque, but we don't
    // handle object ==> opaque casts correctly.  (In codegen, opaque behaves
    // like an lvalue, but in the type system it isn't one.)
    __primitive("local_check", x);
    chpl_memhook_free_pre(__primitive("cast_to_void_star", x));
    __primitive("task_free", x);
  }

  proc chpl_getPrivatizedCopy(type objectType, objectPid:int): objectType
    return __primitive("chpl_getPrivatizedClass", nil:objectType, objectPid);

//########################################################################{
//# Locale diagnostics
//#

  proc locale.totalThreads() {
    var totalThreads: int;
    extern proc chpl_task_getNumThreads() : int;
    on this do totalThreads = chpl_task_getNumThreads();
    return totalThreads;
  }

  proc locale.idleThreads() {
    var idleThreads: int;
    extern proc chpl_task_getNumIdleThreads() : int;
    on this do idleThreads = chpl_task_getNumIdleThreads();
    return idleThreads;
  }

  proc locale.queuedTasks() {
    var queuedTasks: int;
    extern proc chpl_task_getNumQueuedTasks() : int;
    on this do queuedTasks = chpl_task_getNumQueuedTasks();
    return queuedTasks;
  }

  proc locale.runningTasks() {
    var numTasks: int;
    extern proc chpl_task_getNumRunningTasks() : int;
    on this do numTasks = chpl_task_getNumRunningTasks();
    return numTasks;
  }

  proc locale.blockedTasks() {
    var blockedTasks: int;
    extern proc chpl_task_getNumBlockedTasks() : int;
    on this do blockedTasks = chpl_task_getNumBlockedTasks();
    return blockedTasks;
  }

//########################################################################}

}

// ChapelLocale.chpl
//
pragma "no use ChapelStandard"
module ChapelLocale {

  //
  // An abstract class. Specifies the required locale interface.
  // Each locale implementation must inherit from this class.
  //
  class locale {
    //- Constructor
    proc locale() {
// Now we find we have to create locales early, so _here can be non-nil.
      // compilerError("cannot create instances of the 'locale' class");
    }

    //------------------------------------------------------------------------{
    //- Fields and accessors defined for all locale types (not overridable)
    //-

    // Every locale has a parent, except for the root locale.
    // The parent of the root locale is nil (by definition).
    const parent : locale;

    // To be removed from the required interface once legacy code is adjusted.
    const numCores: int;

    // In legacy code, the id accessor is used to obtain the node id, so it
    // should probably be renamed as node_id.
    // As an accessor, it is statically bound, which is also a problem....
    proc id : int return chpl_id();
    proc name return chpl_name();
    //------------------------------------------------------------------------}

    //------------------------------------------------------------------------{
    //- User Interface Methods (overridable)
    //-

    // Returns a globally unique locale identifier.
    // This routine is dynamically dispatched, so it can be overridden in concrete classes.
    proc chpl_id() : int {
      _throwPVFCError();
      return -1;
    }

    proc chpl_name() : string {
      _throwPVFCError();
      return "";
    }

    // A useful default definition is provided (not pure virtual).
    proc readWriteThis(f) {
      f <~> name;
    }

    proc getChildCount() : int {
      _throwPVFCError();
      return 0;
    }

// Part of the required locale interface.
// Commented out because presently iterators are statically bound.
//    iter getChildIndices() : int {
//      for idx in this.getChildSpace do
//        yield idx;
//    }

    proc addChild(loc:locale)
    {
      _throwPVFCError();
    }

    proc getChild(idx:int) : locale {
      _throwPVFCError();
      return this;
    }

// Part of the required locale interface.
// Commented out because presently iterators are statically bound.
//    iter getChildren() : locale  {
//    _throwPVFCError();
//      yield 0;
//    }

    //------------------------------------------------------------------------}

    //------------------------------------------------------------------------{
    //- Compiler Interface Methods (overridable)
    //-

    // Part of the required locale interface.
    // These routines are called by the compiler to implement locale-aware task control.
    // They should be overridden in concrete locale classes as necessary.
    proc taskInit() : void {}
    proc taskExit() : void {}

    proc alloc(nbytes:int) {
      extern proc chpl_malloc(nbytes:int) : opaque;
      return chpl_malloc(nbytes);
    }

    proc calloc(count:int, nbytes:int) {
      extern proc chpl_calloc(count:int, nbytes:int) : opaque;
      return chpl_calloc(count, nbytes);
    }

    proc realloc(x:object, nbytes:int) {
      extern proc chpl_realloc(x:object, nbytes:int) : opaque;
      return chpl_realloc(x, nbytes);
    }

    proc free(x:object) {
      extern proc chpl_free(x:object) : void;
      chpl_free(x);
    }
    //------------------------------------------------------------------------}
  }

  class AbstractLocaleModel : locale {
    // This will be used for interfaces that will be common to all
    // (non-RootLocale) locale models
  }

  // rootLocale is declared to be of type locale rather than
  // RootLocale because doing so would make locales depend on arrays
  // which depend on locales, etc.
  //
  // If we had a way to express domain and array return types abstractly,
  // that problem would go away. <hilde>
  //
  // The rootLocale is private to each locale.  It cannot be
  // initialized until LocaleModel is initialized.  To disable this
  // replication, set replicateRootLocale to false.
  pragma "private" var rootLocale : locale = nil;
  config param replicateRootLocale = true;

  // The rootLocale needs to be initalized on all locales prior to
  // initializing the Locales array.  Unfortunately, the rootLocale
  // cannot be properly replicated until DefaultRectangular can be
  // initialized (as the private copies of the defaultDist are
  // needed).  We remedy this by initializing a rootLocale on locale 0
  // (called origRootLocale), and setting all locales' rootLocale to
  // origRootLocale.  Later, after DefaultRectangular can be
  // initialized, we create local copies of the rootLocale (and the
  // Locales array).  This is being done in the InitPrivateGlobals
  // module.
  //
  var origRootLocale : locale = nil;

  class AbstractRootLocale : locale {
    // These functions are used to establish values for Locales[] and
    // LocaleSpace -- an array of locales and its correponding domain
    // which are used as the default set of targetLocales in many
    // distributions.
    proc getDefaultLocaleSpace() {
      _throwPVFCError();
      const emptyLocaleSpace: domain(1) = {1..0};
      return emptyLocaleSpace;
    }

    proc getDefaultLocaleArray() {
      _throwPVFCError();
      const emptyLocaleSpace: domain(1) = {1..0};
      const emptyLocales: [emptyLocaleSpace] locale;
      return emptyLocales;
    }

    proc localeIDtoLocale(id : chpl_localeID_t) : locale {
      _throwPVFCError();
      return this;
    }

    // These iterators are to be used by RootLocale:init() to
    // initialize the LocaleModel.  The calling loop body cannot
    // contain any non-local code, since the rootLocale is not yet
    // initialized.
    iter initOnLocales() {
      if numLocales > 1 then
        halt("The locales must be initialized in parallel");
      for locIdx in (origRootLocale:RootLocale).getDefaultLocaleSpace() {
        yield locIdx;
        rootLocale = origRootLocale;
      }
    }

    iter initOnLocales(param tag: iterKind)
      where tag==iterKind.leader {
      for locIdx in (origRootLocale:RootLocale).getDefaultLocaleSpace() {
        var locID = chpl_buildLocaleID(locIdx:chpl_nodeID_t, 0:chpl_sublocID_t);
        // sublocale part of locID needs to be any
        on __primitive("chpl_on_locale_num", locID) {
          yield locIdx;
          rootLocale = origRootLocale;
        }
      }
    }

    iter initOnLocales(param tag: iterKind, followThis)
      where tag==iterKind.follower {
      yield followThis;
    }
  }

  // This function is called in the LocalesArray module to initialize
  // the rootLocale.  It sets up the origRootLocale and also includes
  // set up of the each locale's LocaleModel via DefaulRootLocale:init().
  //
  // The init() function must use chpl_rootLocale_locales() to iterate
  // (in parallel) over the locales to set up the LocaleModel object.
  // In addition, the initial 'here' must be set.
  //
  proc chpl_init_rootLocale() {
    origRootLocale = new RootLocale();

    (origRootLocale:RootLocale).init();

    // Programs traditionally expect the startup process to run on
    // Locales[0], so this is how we mimic that behavior.
    // Note that this means we have to ask for here.parent or rootLocale
    // to get the root locale of the default architecture.
    var loc = (origRootLocale:RootLocale).getDefaultLocaleArray()[0];
    __primitive("_task_set_here_ptr", loc);
    var locID = chpl_buildLocaleID(0:chpl_nodeID_t, 0:chpl_sublocID_t);
    __primitive("_task_set_locale_id", locID);
  }

  // This function sets up a private copy of rootLocale by replicating
  // origRootLocale and resets the Locales array to point to the local
  // copy.  It should be called on every locale except locale 0 after
  // it is safe to do so (after defaultDist is initialized).
  proc chpl_rootLocaleInitPrivate() {
    if !replicateRootLocale then return;
    // set rootLocale to a local copy
    var newRootLocale = new RootLocale();
    newRootLocale.getDefaultLocaleArray() =
      (origRootLocale:RootLocale).getDefaultLocaleArray();
    rootLocale = newRootLocale;
    // We mimic a private Locales array alias by using the move
    // primitive.  Note that this leaks the original local Locales
    // array wrapper.
    __primitive("move", Locales, (rootLocale:RootLocale).getDefaultLocaleArray());
  }

  // Returns a wide pointer to the locale with the given id.
  proc chpl_localeID_to_locale(id : chpl_localeID_t) : locale {
    if rootLocale then
      return (rootLocale:AbstractRootLocale).localeIDtoLocale(id);
    else
      // For code prior to rootLocale initialization
      return here;
  }

  // This returns the current "here" pointer.
  // It uses a primitive to suck the here pointer out of task-private storage.
  // On local builds, the primitive returns a narrow pointer;
  // otherwise, a wide pointer.
  //
  // Perhaps we can move this into the compiler as a special keyword....
  inline proc here return __primitive("_task_get_here_ptr");

  // We need a temporary value for "here" before the architecture is defined.
  // This is due to the fact that "here" is used for memory and task control
  // in setting up the architecture itself.
  // Its type should probably be renamed dummyLocale or something representative.
  // The dummy locale provides system-default tasking and memory management.
  __primitive("_task_set_here_ptr", new locale());

  pragma "insert line file info"
  extern proc chpl_memhook_malloc_pre(number:int, size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_malloc_post(ptr:opaque, number:int,
                                       size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_realloc_pre(ptr:object, size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_realloc_post(newPtr:opaque, ptr:object,
                                        size:int, md:int(16)): void;
  pragma "insert line file info"
  extern proc chpl_memhook_free_pre(ptr:opaque): void;
  extern proc chpl_memhook_md_num(): int(16);

  // Here be dragons: If the return type is specified, then normalize.cpp inserts
  // an initializer for the return value which calls its constructor, which calls
  // chpl_here_alloc ad infinitum.  But if the return type is left off, it works!

  // The allocator pragma is used by scalar replacement.
  pragma "allocator"
  pragma "no sync demotion"
  pragma "insert line file info"
  proc chpl_here_alloc(x, md:int(16)) {
    var nbytes = __primitive("sizeof", x);
    chpl_memhook_malloc_pre(1, nbytes, md + chpl_memhook_md_num());
    var mem = __primitive("task_alloc", nbytes);
    chpl_memhook_malloc_post(mem, 1, nbytes, md + chpl_memhook_md_num());
    return __primitive("cast", x.type, mem);
  }

  pragma "allocator"
  pragma "no sync demotion"
  pragma "insert line file info"
  proc chpl_here_calloc(x, number:int, md:int(16)) {
    extern proc chpl_task_calloc(number:int, nbytes:int) : opaque;
    var nbytes = __primitive("sizeof", x);
    chpl_memhook_malloc_pre(number, nbytes, md + chpl_memhook_md_num());
    var mem = chpl_task_calloc(number, nbytes);
    chpl_memhook_malloc_post(mem, number, nbytes, md + chpl_memhook_md_num());
    return __primitive("cast", x.type, mem);
  }

  pragma "allocator"
  pragma "no sync demotion"
  pragma "insert line file info"
  proc chpl_here_realloc(x, md:int(16)) {
    var nbytes = __primitive("sizeof", x);
    chpl_memhook_realloc_pre(x, nbytes, md + chpl_memhook_md_num());
    var mem = __primitive("task_realloc", x:object, nbytes);
    chpl_memhook_realloc_post(mem, x, nbytes, md + chpl_memhook_md_num());
    return __primitive("cast", x.type, mem);
  }

  pragma "no sync demotion"
  pragma "insert line file info"
  proc chpl_here_free(x) {
    // TODO: The pointer should really be of type opaque, but we don't
    // handle object ==> opaque casts correctly.  (In codegen, opaque behaves
    // like an lvalue, but in the type system it isn't one.)
    __primitive("local_check", x);
    chpl_memhook_free_pre(__primitive("cast_to_void_star", x));
    __primitive("task_free", x);
  }

  proc chpl_getPrivatizedCopy(type objectType, objectPid:int): objectType
    return __primitive("chpl_getPrivatizedClass", nil:objectType, objectPid);

//########################################################################{
//# Locale diagnostics
//#

  proc locale.totalThreads() {
    var totalThreads: int;
    extern proc chpl_task_getNumThreads() : int;
    on this do totalThreads = chpl_task_getNumThreads();
    return totalThreads;
  }

  proc locale.idleThreads() {
    var idleThreads: int;
    extern proc chpl_task_getNumIdleThreads() : int;
    on this do idleThreads = chpl_task_getNumIdleThreads();
    return idleThreads;
  }

  proc locale.queuedTasks() {
    var queuedTasks: int;
    extern proc chpl_task_getNumQueuedTasks() : int;
    on this do queuedTasks = chpl_task_getNumQueuedTasks();
    return queuedTasks;
  }

  proc locale.runningTasks() {
    var numTasks: int;
    extern proc chpl_task_getNumRunningTasks() : int;
    on this do numTasks = chpl_task_getNumRunningTasks();
    return numTasks;
  }

  proc locale.blockedTasks() {
    var blockedTasks: int;
    extern proc chpl_task_getNumBlockedTasks() : int;
    on this do blockedTasks = chpl_task_getNumBlockedTasks();
    return blockedTasks;
  }

//########################################################################}

}


Changed the innermost forall loops in fft from loops over distributed domain
slices into forall loops over ranges plus on statements. Since there are
currently memory leaks from distributed domains, the slices cause it to run
out of memory when run at the full problem size.

Also, removed a debugging writeln that caused the fft-testPow4 regression.

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@16402 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

/* This implementation of the FFT benchmark uses radix-4 butterflies
   and is divided into two main phases: one which uses a Block
   distribution and the second which uses a Cyclic distribution.  When
   run on 4**k locales, this guarantees that each butterfly will only
   access local data.  In an optimized implementation, this should
   cause most of the communication to occur when copying the vector
   between Block and Cyclic storage formats.
*/

//
// Use standard modules for Bit operations, Random numbers, Timing, and
// Block and Cyclic distributions
//
use BitOps, Random, Time, BlockDist, CyclicDist;

//
// Use shared user module for computing HPCC problem sizes
//
use HPCCProblemSize;

const radix = 4;               // the radix of this FFT implementation

const numVectors = 2;          // the number of vectors to be stored
type elemType = complex(128);  // the element type of the vectors
type idxType = int(64);        // the index type of the vectors

//
// A configuration constant defining log2(problem size) -- n -- and a
// constant defining the problem size itself -- m
//
config const n = computeProblemSize(numVectors, elemType, returnLog2 = true);
const m = 2**n;

//
// The number of tasks to use per Chapel locale in parallel loops
//
config const tasksPerLocale = here.numCores;

//
// Configuration constants defining the epsilon and threshold values
// used to verify the result
//
config const epsilon = 2.0 ** -51.0,
             threshold = 16.0;

//
// Configuration constants to indicate whether or not to use a
// pseudo-random seed (based on the clock) or a fixed seed; and to
// specify the fixed seed explicitly
//
config const useRandomSeed = true,
             seed = if useRandomSeed then SeedGenerator.clockMS else 314159265;

//
// Configuration constants to control what's printed -- benchmark
// parameters, input and output arrays, and/or statistics
//
config const printParams = true,
             printArrays = false,
             printStats = true;

//
// The program entry point
//
def main() {
  printConfiguration();          // print the problem size

  //
  // This implementation assumes 4**k locales due to its assertion that
  // all butterflies are local to a given locale
  //
  assert(4**log4(numLocales) == numLocales,
         "numLocales must be a power of 4 for this fft implementation");

  //
  // TwiddleDom describes the index set used to define the vector of
  // twiddle values and is a 1D domain indexed by 64-bit ints from 0
  // to m/4-1 stored using the block distribution TwiddleDist.
  // Twiddles is the vector of twiddle values.
  //
  const TwiddleDist = distributionValue(new Block(1, idxType, bbox=[0..m/4-1]));
  const TwiddleDom: domain(1, idxType) distributed TwiddleDist = [0..m/4-1];
  var Twiddles: [TwiddleDom] elemType;

  //
  // ProblemSpace describes the abstract problem space used for the
  // FFT benchmark: the indices 0..m-1
  //
  const ProblemSpace = [0..m-1];

  //
  // BlkDist describes the problem space as distributed in a Block
  // manner between the Locales where ProblemSpace defines the
  // bounding box used to compute the blocking.  BlkDom defines the
  // Block-distributed problem space and is used to define the vectors
  // z (used to store the input vector) and ZBlk (used for the first
  // half of the FFT phases).
  //
  const BlkDist = distributionValue(new Block(1, idxType, bbox=ProblemSpace,
                                              tasksPerLocale=tasksPerLocale));
  const BlkDom: domain(1, idxType) distributed BlkDist = ProblemSpace;
  var Zblk, z: [BlkDom] elemType;

  //
  // CycDist describes the problem space as distributed in a Cyclic
  // manner between the Locales where locale #0 stores element 0.
  // CycDom defines the Cyclic-distributed problem space and is used
  // to define the Zcyc vector, used for the second half of the FFT
  // phases.
  //
  const CycDist = distributionValue(new Cyclic(1, idxType,
                                               tasksPerLocale=tasksPerLocale));
  const CycDom: domain(1, idxType) distributed CycDist = ProblemSpace;
  var Zcyc: [CycDom] elemType;

  initVectors(Twiddles, z);            // initialize twiddles and input vector z

  const startTime = getCurrentTime();  // capture the start time

  Zblk = conjg(z);                        // store the conjugate of z in Zblk
  bitReverseShuffle(Zblk);                // permute Zblk

  dfft(Zblk, Twiddles, cyclicPhase=false); // compute the DFFT, block phases

  forall (b, c) in (Zblk, Zcyc) do       // copy vector to Cyclic storage
    c = b;

  dfft(Zcyc, Twiddles, cyclicPhase=true); // compute the DFFT, cyclic phases

  forall (b, c) in (Zblk, Zcyc) do        // copy vector back to Block storage
    b = c;

  const execTime = getCurrentTime() - startTime;     // store the elapsed time

  const validAnswer = verifyResults(z, Zblk, Zcyc, Twiddles); // validate answer
  printResults(validAnswer, execTime);               // print the results
}

//
// compute the discrete fast Fourier transform of a vector A declared
// over domain ADom using twiddle vector W
//
def dfft(A: [?ADom], W, cyclicPhase) {
  const numElements = A.numElements;
  //
  // loop over the phases of the DFT sequentially using custom
  // iterator genDFTStrideSpan that yields the stride and span for
  // each bank of butterfly calculations
  //
  for (str, span) in genDFTStrideSpan(numElements, cyclicPhase) {
    //
    // loop in parallel over each of the banks of butterflies with
    // shared twiddle factors, zippering with the unbounded range
    // 0.. to get the base twiddle indices
    //
    forall (bankStart, twidIndex) in (ADom by 2*span, 0..) {
      //
      // compute the first set of multipliers for the low bank
      //
      var wk2 = W(twidIndex),
          wk1 = W(2*twidIndex),
          wk3 = (wk1.re - 2 * wk2.im * wk1.im,
                 2 * wk2.im * wk1.re - wk1.im):elemType;
      //
      // loop in parallel over the low bank, computing butterflies
      // Note: lo..#num         == lo, lo+1, lo+2, ..., lo+num-1
      //       lo.. by str #num == lo, lo+str, lo+2*str, ... lo+(num-1)*str
      //
      forall lo in bankStart..#str do
        on ADom.dist.ind2loc(lo) do
          local butterfly(wk1, wk2, wk3, A.localSlice(lo..by str #radix));

      //
      // update the multipliers for the high bank
      //
      wk1 = W(2*twidIndex+1);
      wk3 = (wk1.re - 2 * wk2.re * wk1.im,
             2 * wk2.re * wk1.re - wk1.im):elemType;
      wk2 *= 1.0i;

      //
      // loop in parallel over the high bank, computing butterflies
      //
      forall lo in bankStart+span..#str do
        on ADom.dist.ind2loc(lo) do
          local butterfly(wk1, wk2, wk3, A.localSlice(lo.. by str #radix));
    }
  }

  if cyclicPhase {
    //
    // Do the last set of butterflies...
    //
    const str = radix**log4(numElements-1);
    //
    // ...using the radix-4 butterflies with 1.0 multipliers if the
    // problem size is a power of 4
    //
    if (str*radix == numElements) {
      forall lo in 0..#str do
        on ADom.dist.ind2loc(lo) do
          local butterfly(1.0, 1.0, 1.0, A.localSlice(lo.. by str # radix));
    }
    //
    // ...otherwise using a simple radix-2 butterfly scheme
    //
    else
      forall lo in 0..#str do
        on ADom.dist.ind2loc(lo) do
          local {
            const a = A(lo),
                  b = A(lo+str);
            A(lo)     = a + b;
            A(lo+str) = a - b;
          }
  }
}

//
// this is the radix-4 butterfly routine that takes multipliers wk1,
// wk2, and wk3 and a 4-element array (slice) A.
//
def butterfly(wk1, wk2, wk3, X:[0..3]) {
  var x0 = X(0) + X(1),
      x1 = X(0) - X(1),
      x2 = X(2) + X(3),
      x3rot = (X(2) - X(3))*1.0i;

  X(0) = x0 + x2;                   // compute the butterfly in-place on X
  x0 -= x2;
  X(2) = wk2 * x0;
  x0 = x1 + x3rot;
  X(1) = wk1 * x0;
  x0 = x1 - x3rot;
  X(3) = wk3 * x0;
}

//
// this iterator generates the stride and span values for the phases
// of the DFFT simply by yielding tuples: (radix**i, radix**(i+1))
//
def genDFTStrideSpan(numElements, cyclicPhase) {
  const (start, end) = if !cyclicPhase then (1, numLocales:idxType)
                                       else (numLocales, numElements-1);
  var stride = start;
  for i in log4(start)+1..log4(end):int {
    const span = stride * radix;
    yield (stride, span);
    stride = span;
  }
}

//
// Print the problem size
//
def printConfiguration() {
  if (printParams) {
    if (printStats) then printLocalesTasks(tasksPerLocale=tasksPerLocale);
    printProblemSize(elemType, numVectors, m);
  }
}

//
// Initialize the twiddle vector and random input vector and
// optionally print them to the console
//
def initVectors(Twiddles, z) {
  computeTwiddles(Twiddles);
  bitReverseShuffle(Twiddles);

  fillRandom(z, seed);

  if (printArrays) {
    writeln("After initialization, Twiddles is: ", Twiddles, "\n");
    writeln("z is: ", z, "\n");
  }
}

//
// Compute the twiddle vector values
//
def computeTwiddles(Twiddles) {
  const numTwdls = Twiddles.numElements,
        delta = 2.0 * atan(1.0) / numTwdls;

  Twiddles(0) = 1.0;
  Twiddles(numTwdls/2) = let x = cos(delta * numTwdls/2)
                          in (x, x): elemType;
  forall i in 1..numTwdls/2-1 {
    const x = cos(delta*i),
          y = sin(delta*i);
    Twiddles(i)            = (x, y): elemType;
    Twiddles(numTwdls - i) = (y, x): elemType;
  }
}

//
// Perform a permutation of the argument vector by reversing the bits
// of the indices
//
def bitReverseShuffle(Vect: [?Dom]) {
  const numBits = log2(Vect.numElements),
        Perm: [i in Dom] Vect.eltType = Vect(bitReverse(i, revBits=numBits));
  Vect = Perm;
}

//
// Reverse the low revBits bits of val
//
def bitReverse(val: ?valType, revBits = 64) {
  param mask = 0x0102040810204080;
  const valReverse64 = bitMatMultOr(mask, bitMatMultOr(val:uint(64), mask)),
        valReverse = bitRotLeft(valReverse64, revBits);
  return valReverse: valType;
}

//
// Compute the log base 4 of x
//
def log4(x) return logBasePow2(x, 2);

//
// verify that the results are correct by reapplying the dfft and then
// calculating the maximum error, comparing against epsilon
//
def verifyResults(z, Zblk, Zcyc, Twiddles) {
  if (printArrays) then writeln("After FFT, Z is: ", Zblk, "\n");

  Zblk = conjg(Zblk) / m;
  bitReverseShuffle(Zblk);
  dfft(Zblk, Twiddles, cyclicPhase=false);
  forall (b, c) in (Zblk, Zcyc) do
    c = b;
  dfft(Zcyc, Twiddles, true);
  forall (b, c) in (Zblk, Zcyc) do
    b = c;

  if (printArrays) then writeln("After inverse FFT, Z is: ", Zblk, "\n");

  var maxerr = max reduce sqrt((z.re - Zblk.re)**2 + (z.im - Zblk.im)**2);
  maxerr /= (epsilon * n);
  if (printStats) then writeln("error = ", maxerr);

  return (maxerr < threshold);
}

//
// print out sucess/failure, the timing, and the Gflop/s value
//
def printResults(successful, execTime) {
  writeln("Validation: ", if successful then "SUCCESS" else "FAILURE");
  if (printStats) {
    writeln("Execution time = ", execTime);
    writeln("Performance (Gflop/s) = ", 5 * (m * n / execTime) * 1e-9);
  }
}

/* This implementation of the FFT benchmark uses radix-4 butterflies
   and is divided into two main phases: one which uses a Block
   distribution and the second which uses a Cyclic distribution.  When
   run on 4**k locales, this guarantees that each butterfly will only
   access local data.  In an optimized implementation, this should
   cause most of the communication to occur when copying the vector
   between Block and Cyclic storage formats.
*/

//
// Use standard modules for Bit operations, Random numbers, Timing, and
// Block and Cyclic distributions
//
use BitOps, Random, Time, BlockDist, CyclicDist;

//
// Use shared user module for computing HPCC problem sizes
//
use HPCCProblemSize;

const radix = 4;               // the radix of this FFT implementation

const numVectors = 2;          // the number of vectors to be stored
type elemType = complex(128);  // the element type of the vectors
type idxType = int(64);        // the index type of the vectors

//
// A configuration constant defining log2(problem size) -- n -- and a
// constant defining the problem size itself -- m
//
config const n = computeProblemSize(numVectors, elemType, returnLog2 = true);
const m = 2**n;

//
// The number of tasks to use per Chapel locale in parallel loops
//
config const tasksPerLocale = here.numCores;

//
// Configuration constants defining the epsilon and threshold values
// used to verify the result
//
config const epsilon = 2.0 ** -51.0,
             threshold = 16.0;

//
// Configuration constants to indicate whether or not to use a
// pseudo-random seed (based on the clock) or a fixed seed; and to
// specify the fixed seed explicitly
//
config const useRandomSeed = true,
             seed = if useRandomSeed then SeedGenerator.clockMS else 314159265;

//
// Configuration constants to control what's printed -- benchmark
// parameters, input and output arrays, and/or statistics
//
config const printParams = true,
             printArrays = false,
             printStats = true;

//
// The program entry point
//
def main() {
  printConfiguration();          // print the problem size

  //
  // This implementation assumes 4**k locales due to its assertion that
  // all butterflies are local to a given locale
  //
  assert(4**log4(numLocales) == numLocales,
         "numLocales must be a power of 4 for this fft implementation");

  //
  // TwiddleDom describes the index set used to define the vector of
  // twiddle values and is a 1D domain indexed by 64-bit ints from 0
  // to m/4-1 stored using the block distribution TwiddleDist.
  // Twiddles is the vector of twiddle values.
  //
  const TwiddleDist = distributionValue(new Block(1, idxType, bbox=[0..m/4-1]));
  const TwiddleDom: domain(1, idxType) distributed TwiddleDist = [0..m/4-1];
  var Twiddles: [TwiddleDom] elemType;

  //
  // ProblemSpace describes the abstract problem space used for the
  // FFT benchmark: the indices 0..m-1
  //
  const ProblemSpace = [0..m-1];

  //
  // BlkDist describes the problem space as distributed in a Block
  // manner between the Locales where ProblemSpace defines the
  // bounding box used to compute the blocking.  BlkDom defines the
  // Block-distributed problem space and is used to define the vectors
  // z (used to store the input vector) and ZBlk (used for the first
  // half of the FFT phases).
  //
  const BlkDist = distributionValue(new Block(1, idxType, bbox=ProblemSpace,
                                              tasksPerLocale=tasksPerLocale));
  const BlkDom: domain(1, idxType) distributed BlkDist = ProblemSpace;
  var Zblk, z: [BlkDom] elemType;

  //
  // CycDist describes the problem space as distributed in a Cyclic
  // manner between the Locales where locale #0 stores element 0.
  // CycDom defines the Cyclic-distributed problem space and is used
  // to define the Zcyc vector, used for the second half of the FFT
  // phases.
  //
  const CycDist = distributionValue(new Cyclic(1, idxType,
                                               tasksPerLocale=tasksPerLocale));
  const CycDom: domain(1, idxType) distributed CycDist = ProblemSpace;
  var Zcyc: [CycDom] elemType;

  initVectors(Twiddles, z);            // initialize twiddles and input vector z

  const startTime = getCurrentTime();  // capture the start time

  Zblk = conjg(z);                        // store the conjugate of z in Zblk
  bitReverseShuffle(Zblk);                // permute Zblk

  dfft(Zblk, Twiddles, cyclicPhase=false); // compute the DFFT, block phases

  forall (b, c) in (Zblk, Zcyc) do       // copy vector to Cyclic storage
    c = b;

  dfft(Zcyc, Twiddles, cyclicPhase=true); // compute the DFFT, cyclic phases

  forall (b, c) in (Zblk, Zcyc) do        // copy vector back to Block storage
    b = c;

  const execTime = getCurrentTime() - startTime;     // store the elapsed time

  const validAnswer = verifyResults(z, Zblk, Zcyc, Twiddles); // validate answer
  printResults(validAnswer, execTime);               // print the results
}

//
// compute the discrete fast Fourier transform of a vector A declared
// over domain ADom using twiddle vector W
//
def dfft(A: [?ADom], W, cyclicPhase) {
  const numElements = A.numElements;
  //
  // loop over the phases of the DFT sequentially using custom
  // iterator genDFTStrideSpan that yields the stride and span for
  // each bank of butterfly calculations
  //
  for (str, span) in genDFTStrideSpan(numElements, cyclicPhase) {
    //
    // loop in parallel over each of the banks of butterflies with
    // shared twiddle factors, zippering with the unbounded range
    // 0.. to get the base twiddle indices
    //
    forall (bankStart, twidIndex) in (ADom by 2*span, 0..) {
      //
      // compute the first set of multipliers for the low bank
      //
      var wk2 = W(twidIndex),
          wk1 = W(2*twidIndex),
          wk3 = (wk1.re - 2 * wk2.im * wk1.im,
                 2 * wk2.im * wk1.re - wk1.im):elemType;
      //
      // loop in parallel over the low bank, computing butterflies
      // Note: lo..#num         == lo, lo+1, lo+2, ..., lo+num-1
      //       lo.. by str #num == lo, lo+str, lo+2*str, ... lo+(num-1)*str
      //
      forall lo in ADom[bankStart..#str] do
        local butterfly(wk1, wk2, wk3, A.localSlice(lo..by str #radix));

      //
      // update the multipliers for the high bank
      //
      wk1 = W(2*twidIndex+1);
      wk3 = (wk1.re - 2 * wk2.re * wk1.im,
             2 * wk2.re * wk1.re - wk1.im):elemType;
      wk2 *= 1.0i;

      //
      // loop in parallel over the high bank, computing butterflies
      //
      forall lo in ADom[bankStart+span..#str] do
        local butterfly(wk1, wk2, wk3, A.localSlice(lo.. by str #radix));
    }
  }

  if cyclicPhase {
    //
    // Do the last set of butterflies...
    //
    const str = radix**log4(numElements-1);
    //
    // ...using the radix-4 butterflies with 1.0 multipliers if the
    // problem size is a power of 4
    //
    if (str*radix == numElements) {
      writeln("looping over ", 0..#str, "; slice = lo.. by ", str, " # ", radix);
      forall lo in ADom[0..#str] do
        local butterfly(1.0, 1.0, 1.0, A.localSlice(lo.. by str # radix));
    }
    //
    // ...otherwise using a simple radix-2 butterfly scheme
    //
    else
      forall lo in ADom[0..#str] do
        local {
          const a = A(lo),
                b = A(lo+str);
          A(lo)     = a + b;
          A(lo+str) = a - b;
        }
  }
}

//
// this is the radix-4 butterfly routine that takes multipliers wk1,
// wk2, and wk3 and a 4-element array (slice) A.
//
def butterfly(wk1, wk2, wk3, X:[0..3]) {
  var x0 = X(0) + X(1),
      x1 = X(0) - X(1),
      x2 = X(2) + X(3),
      x3rot = (X(2) - X(3))*1.0i;

  X(0) = x0 + x2;                   // compute the butterfly in-place on X
  x0 -= x2;
  X(2) = wk2 * x0;
  x0 = x1 + x3rot;
  X(1) = wk1 * x0;
  x0 = x1 - x3rot;
  X(3) = wk3 * x0;
}

//
// this iterator generates the stride and span values for the phases
// of the DFFT simply by yielding tuples: (radix**i, radix**(i+1))
//
def genDFTStrideSpan(numElements, cyclicPhase) {
  const (start, end) = if !cyclicPhase then (1, numLocales:idxType)
                                       else (numLocales, numElements-1);
  var stride = start;
  for i in log4(start)+1..log4(end):int {
    const span = stride * radix;
    yield (stride, span);
    stride = span;
  }
}

//
// Print the problem size
//
def printConfiguration() {
  if (printParams) {
    if (printStats) then printLocalesTasks(tasksPerLocale=tasksPerLocale);
    printProblemSize(elemType, numVectors, m);
  }
}

//
// Initialize the twiddle vector and random input vector and
// optionally print them to the console
//
def initVectors(Twiddles, z) {
  computeTwiddles(Twiddles);
  bitReverseShuffle(Twiddles);

  fillRandom(z, seed);

  if (printArrays) {
    writeln("After initialization, Twiddles is: ", Twiddles, "\n");
    writeln("z is: ", z, "\n");
  }
}

//
// Compute the twiddle vector values
//
def computeTwiddles(Twiddles) {
  const numTwdls = Twiddles.numElements,
        delta = 2.0 * atan(1.0) / numTwdls;

  Twiddles(0) = 1.0;
  Twiddles(numTwdls/2) = let x = cos(delta * numTwdls/2)
                          in (x, x): elemType;
  forall i in 1..numTwdls/2-1 {
    const x = cos(delta*i),
          y = sin(delta*i);
    Twiddles(i)            = (x, y): elemType;
    Twiddles(numTwdls - i) = (y, x): elemType;
  }
}

//
// Perform a permutation of the argument vector by reversing the bits
// of the indices
//
def bitReverseShuffle(Vect: [?Dom]) {
  const numBits = log2(Vect.numElements),
        Perm: [i in Dom] Vect.eltType = Vect(bitReverse(i, revBits=numBits));
  Vect = Perm;
}

//
// Reverse the low revBits bits of val
//
def bitReverse(val: ?valType, revBits = 64) {
  param mask = 0x0102040810204080;
  const valReverse64 = bitMatMultOr(mask, bitMatMultOr(val:uint(64), mask)),
        valReverse = bitRotLeft(valReverse64, revBits);
  return valReverse: valType;
}

//
// Compute the log base 4 of x
//
def log4(x) return logBasePow2(x, 2);

//
// verify that the results are correct by reapplying the dfft and then
// calculating the maximum error, comparing against epsilon
//
def verifyResults(z, Zblk, Zcyc, Twiddles) {
  if (printArrays) then writeln("After FFT, Z is: ", Zblk, "\n");

  Zblk = conjg(Zblk) / m;
  bitReverseShuffle(Zblk);
  dfft(Zblk, Twiddles, cyclicPhase=false);
  forall (b, c) in (Zblk, Zcyc) do
    c = b;
  dfft(Zcyc, Twiddles, true);
  forall (b, c) in (Zblk, Zcyc) do
    b = c;

  if (printArrays) then writeln("After inverse FFT, Z is: ", Zblk, "\n");

  var maxerr = max reduce sqrt((z.re - Zblk.re)**2 + (z.im - Zblk.im)**2);
  maxerr /= (epsilon * n);
  if (printStats) then writeln("error = ", maxerr);

  return (maxerr < threshold);
}

//
// print out sucess/failure, the timing, and the Gflop/s value
//
def printResults(successful, execTime) {
  writeln("Validation: ", if successful then "SUCCESS" else "FAILURE");
  if (printStats) {
    writeln("Execution time = ", execTime);
    writeln("Performance (Gflop/s) = ", 5 * (m * n / execTime) * 1e-9);
  }
}


Verify pragma "no doc" works on type aliases, and extern types (opaque and not).

module Foo {
  pragma "no doc"
  config var blah: int; // No comment, should have nothing printed out

  /* This config var has a comment before it. */
  pragma "no doc"
  config var blah2: int;

  pragma "no doc"
    /* This config var has a comment after the pragma */
  config var blah3: int;

  config var blah4: int; // Should be printed, but without comment

  /* This type should not be doc'd. */
  pragma "no doc"
  type myint = int(64);

  /* This external type should not be doc'd. */
  pragma "no doc"
  extern type exT = 2*real(64);

  /* This opaque external type should not be doc'd. */
  pragma "no doc"
  extern type MyExT;

  pragma "no doc"
  proc a () {  }

  /* This function has a comment before it. */
  pragma "no doc"
  proc b () {  }

  pragma "no doc"
  /* This function has a comment after the pragma. */
  proc c () {  }

  proc d() {
    // Should be printed, but without comment
  }

  pragma "no doc"
  class alsoIgnoreMe {
    type t;
    var b: t;
  }

  pragma "no doc"
    /* This class has a comment after the pragma */
  class alsoIgnoreMe2 {
    type t;
    var b: t;
  }

  /* This class has a comment before the pragma */
  pragma "no doc"
  class alsoIgnoreMe3 {
    type t;
    var b: t;
  }

  class bar {
    // No class comment.  Should not grab previous class comment.

    pragma "no doc"
    var ignoreMe: bool;

    /* This field has a comment before it */
    pragma "no doc"
    var ignoreMe2: bool;

    pragma "no doc"
    /* This field has a comment after the pragma */
    var ignoreMe3: bool;

    var showMe: bool;
    // This is the only field that should be printed
  }

  /* This is an undocumented module. */
  pragma "no doc"
  module invisible {

    /* This class is undocumented, since its module is undocumented. */
    class MyC {}
  }
}

pragma "no doc"
module toBeIgnored {

  class otherwiseSeen {
    var andAField: string;
  }
}

module Foo {
  pragma "no doc"
  config var blah: int; // No comment, should have nothing printed out

  /* This config var has a comment before it. */
  pragma "no doc"
  config var blah2: int;

  pragma "no doc"
    /* This config var has a comment after the pragma */
  config var blah3: int;

  config var blah4: int; // Should be printed, but without comment

  pragma "no doc"
  proc a () {  }

  /* This function has a comment before it. */
  pragma "no doc"
  proc b () {  }

  pragma "no doc"
  /* This function has a comment after the pragma. */
  proc c () {  }

  proc d() {
    // Should be printed, but without comment
  }

  pragma "no doc"
  class alsoIgnoreMe {
    type t;
    var b: t;
  }

  pragma "no doc"
    /* This class has a comment after the pragma */
  class alsoIgnoreMe2 {
    type t;
    var b: t;
  }

  /* This class has a comment before the pragma */
  pragma "no doc"
  class alsoIgnoreMe3 {
    type t;
    var b: t;
  }

  class bar {
    // No class comment.  Should not grab previous class comment.

    pragma "no doc"
    var ignoreMe: bool;

    /* This field has a comment before it */
    pragma "no doc"
    var ignoreMe2: bool;

    pragma "no doc"
    /* This field has a comment after the pragma */
    var ignoreMe3: bool;

    var showMe: bool;
    // This is the only field that should be printed
  }

  /* This is an undocumented module. */
  pragma "no doc"
  module invisible {

    /* This class is undocumented, since its module is undocumented. */
    class MyC {}
  }
}

pragma "no doc"
module toBeIgnored {

  class otherwiseSeen {
    var andAField: string;
  }
}


The difference between no-local and local timings was a result of
iterating through the bytes array to print each individual byte instead
of a single array print.  Updating my fastest version to reflect this.

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@23331 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

config const size : uint = 200;

proc main()
{
  const bytesRequired : uint = (size + 7) / 8;
  const byteRange = 0..#bytesRequired:int(64);
  const sizeRange = 0..#size:int(64);

  var bytes : [sizeRange, byteRange] uint(8);

  const limit : real = 4.0;
  const maxIter : int = 50;

  forall y in sizeRange do
    {
      for bytex in byteRange {
        var byte_acc : uint(8) = 0;

        for x in (bytex*8)..#8 do
          {
            var Zr : real = 0.0;
            var Zi : real = 0.0;
            var Tr : real = 0.0;
            var Ti : real = 0.0;
            const Cr : real = (2.0*x/size - 1.5);
            const Ci : real = (2.0*y/size - 1.0);

            {
              var iterNo : int = maxIter;
              while (iterNo > 0 && (Tr+Ti <= limit))
                {
                  Zi = 2.0*Zr*Zi + Ci;
                  Zr = Tr - Ti + Cr;
                  Tr = Zr * Zr;
                  Ti = Zi * Zi;
                  iterNo -= 1;
                }
            }

            byte_acc <<= 1;
            if(Tr+Ti <= limit) then
              byte_acc |= 0x01;
          }

        bytes(y, bytex) = byte_acc;
      }
    }

  var f = openfd(1);
  var w = f.writer(kind=iokind.native, locking=false);
  w.writef("P4\n%i %i\n", size, size);

  w.write(bytes);
}

config const size : uint = 200;

proc main()
{
  const bytesRequired : uint = (size + 7) / 8;
  const byteRange = 0..#bytesRequired:int(64);
  const sizeRange = 0..#size:int(64);

  var bytes : [sizeRange, byteRange] uint(8);

  const limit : real = 4.0;
  const maxIter : int = 50;

  forall y in sizeRange do
    {
      for bytex in byteRange {
        var byte_acc : uint(8) = 0;

        for x in (bytex*8)..#8 do
          {
            var Zr : real = 0.0;
            var Zi : real = 0.0;
            var Tr : real = 0.0;
            var Ti : real = 0.0;
            const Cr : real = (2.0*x/size - 1.5);
            const Ci : real = (2.0*y/size - 1.0);

            {
              var iterNo : int = maxIter;
              while (iterNo > 0 && (Tr+Ti <= limit))
                {
                  Zi = 2.0*Zr*Zi + Ci;
                  Zr = Tr - Ti + Cr;
                  Tr = Zr * Zr;
                  Ti = Zi * Zi;
                  iterNo -= 1;
                }
            }

            byte_acc <<= 1;
            if(Tr+Ti <= limit) then
              byte_acc |= 0x01;
          }

        bytes(y, bytex) = byte_acc;
      }
    }

  var f = openfd(1);
  var w = f.writer(kind=iokind.native, locking=false);
  w.writef("P4\n%i %i\n", size, size);

  for (x,y) in bytes.domain do {
    w.write(bytes(x,y));
  }
}