Synthetic Semantics
Overview of EMS   |   API Documentation   |   Node.js NPM   |   Download at GitHub

Extended Memory Semantics

EMS stores tags internally that are used for synchronization of user data, allowing synchronization to happen independently of the number or kind of processes accessing the data. The EMS intrinsics like stacks, queues, and transactional memory are built on read, write, and read-modify-write operations that enforce atomic access to JSON objects and values.

EMS memory is an array or key-value store of JSON values accessed using atomic operators and/or transactional memory. Safe parallel access is managed automatically.

EMS Data Tag Transitions & Atomic operations: F=Full, E=Empty, X=Don't Care, RW=Readers-Writer lock (# of current readers) CAS=Compare-and-Swap, FAA=Fetch-and-Add

EMS Collective Operations and Configuration

The API is structurally identical between languages, in many cases the exact same syntax works for both Python2/3 and Node.js. Unlike Python and Node.js, C provides several different kinds of shared memory parallelism, including OpenMP on which the BSP execution is based, the C API does not include functions to initiate or control parallelism.

The C interface uses a structure to describe dynamically typed values defined in ems.h:

#define EMS_TYPE_INVALID ((unsigned char)0)
#define EMS_TYPE_BOOLEAN ((unsigned char)1)
#define EMS_TYPE_STRING ((unsigned char)2)
#define EMS_TYPE_FLOAT ((unsigned char)3)
#define EMS_TYPE_INTEGER ((unsigned char)4)
#define EMS_TYPE_UNDEFINED ((unsigned char)5)
#define EMS_TYPE_JSON ((unsigned char)6)

typedef struct {
     size_t length; // Defined only for JSON and strings
     void *value; // Scalar value or pointer to buffer/string
     unsigned char type; // One of the above EMS_TYPE_ values
} EMSvalueType;

Importing or Requiring EMS
SYNOPSIS Initialize the EMS module, starting all the other threads. Thread identity and processor affinity is assigned when the thread is created. Node/Python only, C parallelism is user managed.

Node.js require('ems') ( nThreads [, threadAffinity [, parallelType [, contextName ] ] ] )
Python import ems
ems.initialize( nThreads [, threadAffinity [, parallelType [, contextName ] ] ] )
C #include "ems.h" // Parallelism in C is always user managed
ARGUMENTS nThreads <Number> Total number of threads the job should use.
threadAffinity <Boolean> (Optional, Default = false, Affects only Linux.) Set the scheduling affinity of each thread to it's own core, assigning over-subscribed threads in a round-robin fashion.
parallelType <String> (Optional, Default=bsp) One of bsp, fj, or user. Execution model: bsp will use EMS' built-in Bulk Synchronous Parallel execution, fj uses EMS' built-in Fork-join execution (Python not supported in v1.4), and user creates no parallelism.
contextName <String> (Optional, Default=anonymous) Unique name of parallel context being initialized, required to distinguish between multiple EMS parallel programs running simultaneously on the same system.

RETURNS json = { nThreads : Number, // Number of threads executing myID : Number // This thread's ID 0..nThreads-1 }
Node.js EXAMPLES ems = require('ems')(process.argv[2]) Use the first command line argument as the number of nodes:
node foo.js 4 executes using 4 threads.
ems = require('ems')() Run on one node
ems = require('ems')(process.argv[2], false, true) Use first command line argument as number of nodes, do not set affinity of the threads to a specific CPU, execute using fork-join parallelism.
Python EXAMPLES import EMS ems = EMS.initialize(4, contextName = "/tmp/EMS_897") Four processes operating in a private context persisting on /tmp
Create a new EMS Array
SYNOPSIS Attach to an existing or create a new EMS array. Creation of new (do not use existing) EMS memory regions implies a barrier, whereas using an existing EMS file will block until the file exists.

Node.js ems.new( [ nElements [, heapSize [, fileName] ] ] )
  ems.new( emsArrayDescriptor )
Python ems.new( [ nElements [, heapSize [, fileName] ] ] )
  ems.new( emsArrayDescriptor )
C int EMSinitialize(int64_t nElements, int64_t heapSize, bool useMap,
                  const char *filename, bool persist, bool useExisting,
                  bool doDataFill, bool fillIsJSON, EMSvalueType *fillValue,
                  bool doSetFEtags, bool setFEtags, int EMSmyID,
                  bool pinThreads, int64_t nThreads, int64_t pctMLock);
ARGUMENTS nElements <Number> (Optional, Default is 1) Maximum number of elements in the EMS array or map.
<Array> An array of dimensions of a multi-dimensional array. A 100×30×50 cube is described by [100, 30, 50].
heapSize <Number> (Optional, Default is 0) Maximum number of bytes reserved for strings, arrays, maps, and object elements in this array. The actual amount of memory allocated for use is rounded up to the nearest power of 2 (until a better memory allocator is implemented) . Additional memory is allocated for bookkeeping. Memory block size is defined in ems_alloc.h: EMS_MEM_BLOCKSZ but should be configurable at create time .
fileName <String> (Optional, Default is anonymous) Fully qualified file name of the file to use as a persistent backing store for the EMS array, tags, and bookkeeping information.
emsArrayDescriptor <Object> As an alternative to scalar argument(s), A complete EMS array descriptor may be passed as the only argument.
emsArrayDescriptor = { dimensions : 100, // Required: Max # elements in EMS array // Integer for 1-D, or array of dims [x, y, z] heapSize : 100000, // Optional, default=0: Space, in bytes, for // strings, maps, and objects. Rounded up to nearest power of two mlock : 0, // Optional, default=0: % of EMS memory to lock into RAM ES6proxies: false, // Optional, default=False: Enable implied read/write in JS useMap : true, // Optional, default=false: Map keys to indexes useExisting : true, // Optional, default=false: // Preserve data if an file already exists persist : true, // Optional, default=true: // Preserve the file after threads exit doDataFill : false, // Optional, default=false: Initialize memory dataFill : undefined,// Optional, If this property is defined, // the EMS memory is filled with this value doSetFEtags: false, // Optional, If true, tags are set to setFEtags. setFEtags : 'full', // Optional, 'full' or 'empty', ignored if doSetFEtags==false filename : '/path/to/file' // Optional, default=anonymous: // Path to the persistent file of this array }
NOTE: ES6 Proxy support varies with version of Node.js, (it may not be supported, require a polyfill and/or command line option, or work with nothing at all) and may impose a performance penalty.

RETURNS <EMS Array | Number> Node & Python return the EMS array, C returns an integer handle to the EMS array.
Node.js EXAMPLES var foo = ems.new(nItems) Create a new non-persistent shared memory EMS array with no heap space. Scalar data (Number, Boolean, Undefined) may be stored in this array, but not strings, arrays, or objects.
var foo = ems.new(nItems, size, '/tmp/EMS_foo') Create a file-backed EMS shared memory space with the filename /tmp/EMS_foo. In addition to the scalar storage, space for strings totaling size bytes is also reserved for strings, arrays, objects, and maps.
Python EXAMPLES x = ems.new({ 'dimensions': [1000], 'heapSize': 20000, 'useMap': True, 'useExisting': False, 'filename': '/tmp/test.ems', 'doSetFEtags': True, 'setFEtags': 'empty' }) Create a new non-persistent shared memory EMS array with 1000 elements, uses mapped keys, and sets all data to Empty.
Parallel Region (Fork-Join execution only)
SYNOPSIS When using fork-join execution, the master thread enters a parallel region by executing func once from each process. The master process first starts all the other processes running the function asynchronously, then executes the function itself synchronously. All processes join (perform a barrier) after completion of the work function. The results of the function are discarded. Global variables on each node are persistent between parallel regions.

Node.js ems.parallel( [args, ...] func )
Python Not implemented in v1.4
C Parallelism to be implemented by application
ARGUMENTS args <Any> Zero or more arguments to be passed to the function.
func <Function> Function to be executed once on every thread. The optional arguments are used when calling the function. Return value is ignored.

Node.js EXAMPLES ems.parallel( doWork ) The function doWork is executed by every thread.
ems.parallel( foo, "Smith", 123, doWork ) The function call doWork(foo, "Smith", 123) is performed once by each process.
Parallel Loops
SYNOPSIS Parallel loop execution, distributing the iterations among all the threads. The function is invoked with one argument, the current iteration number. Iterations are divided among the threads according to the scheduling method specified. Parallel for loops must not be nested. The system should check for this and fall back on serial execution. A barrier is implied at the end.

Node.js ems.parForEach( first, last, function [, scheduling [, minChunk] ] )
Python ems.parForEach( first, last, function [, scheduling [, minChunk] ] )
C Parallelism provided by C program
ARGUMENTS first <Number> Index to start iterating
last <Number> Index to stop iterating (non-inclusive).
func <Function> Loop body, only input argument is current loop index:
function foo(idx) {...}
scheduling <String> If option is omitted, defaults to guided with a minimum chunk size of 1 iteration.
guided [minChunk]: Decreasing amounts of work are assigned to each task until minChunk iterations per thread is reached. Load balancing occurs when new chunks are assigned to threads.
static: Equal number of iterations are given to each thread, no dynamic load balancing is performed.
dynamic: All threads share one index which is atomically incremented by 1 after each iteration. Provides ideal load balancing at the cost of high per-iteration overhead.
minChunk <Number> (Optional, only used when scheduling='guided', default=1) Minimum number of iterations assigned to a single thread.

Node.js EXAMPLES ems.parForEach(0, nItems-1, func) Execute the func function nItems-1 times with indexes 0..nItems-1, inclusive.
ems.parForEach(10000, 20000, func, 'guided', 200) Distribute iterations numbered 10,000-20,000 (inclusive) using the guided method with a minimum chunk size of 200 iterations
Python EXAMPLES ems.parForEach(0, 999, func, 'static') Execute func() 1,000 times with indexes 0..999 inclusive. Distribute the iterations evenly across threads in contiguous blocks.
Barrier Synchronization
SYNOPSIS All the threads must reach the same barrier before proceeding. Failure to call a barrier from every process will result in deadlock. If called outside a parallel region, a barrier has no effect.

Node.js ems.barrier([timeout])
Python ems.barrier([timeout])
C int EMSbarrier(int mmapID, int timeout)
ARGUMENTS timeout <Number> Number of microseconds to wait at a barrier before failing. Defaults to 10000μs.
RETURNS <Number> Amount of time remaining before timeout. If less than or equal to 0, the barrier has failed.

EXAMPLES ems.barrier() All threads reach the barrier before proceeding.
// Shared data is unitialized if(ems.myID == 0) { // One processes initializes shared data shared.writeXF('foo', -43.21); ems.barrier(); } else { ems.barrier(); // Other processes wait for initialization to complete } // All processes can now safely access the initialized data Initialize some shared data and then allow all threads to access it
Critical Region
SYNOPSIS Perform function func() mutually exclusive of other threads. Serializes execution through all critical regions. Named regions would be more like OpenMP

Node.js ems.critical( func [, timeout] )
Python ems.critical( func [, timeout] )
C int EMScriticalEnter(int mmapID, int timeout)
bool EMScriticalExit(int mmapID)
ARGUMENTS func <Function> Function to perform sequentially.
timeout <Number> Number of microseconds to wait before timing out. Defaults to 10000μs.
RETURNS <Boolean> True if critical region executed safely, otherwise False for timeout or other error.

EXAMPLES ems.critical( function() { // Use a shared resource exclusively } ) A shared resource is accessed sequentially, but in no particular order.
Execute on Master Thread Only
SYNOPSIS Perform function func() only on thread 0, implies a barrier.

Node.js ems.master( func )
Python ems.master( func )
C Parallelism provided by C program
ARGUMENTS func <Function> Function to be performed only by task 0. Implied barrier after the function is called.

EXAMPLES ems.master( function() { console.log("Only task 0") } ) Console logging performed only by task 0
Execute once on any thread
SYNOPSIS Perform function func() only once by the first thread to reach the statement. Implies a barrier.

Node.js ems.single( func )
Python ems.single( func )
C Parallelism provided by C program
ARGUMENTS func <Function> Function to be performed once.

EXAMPLES ems.single( function() { console.log("Only first task") } ) Console logging is performed only once.
Print Diagnostic Message
SYNOPSIS Print a diagnostic message to the console with a prefix indicating the task ID.

Node.js ems.diag( message )
Python ems.diag( message )
ARGUMENTS message <String> Text of message to print to the console

EXAMPLES ems.diag( "Hello, world!" ) EMS 3: Hello, world! appears on console

EMS Array Methods

Intrinsic Atomic Operations (AMOs)
Read EMS Memory
SYNOPSIS The read family of EMS memory operations return the data stored in an EMS array element. The value may be any JSON object or intrinsic value.
Python and Javascript support the ability to make EMS data access transparent to different degrees, allowing expressions like emsArray.foo = 123;
read
Immediately and unconditionally returns the stored value, ignoring the tag state. Reading uninitialized mapped indexes will return undefined regardless of the default value. In contrast to that, intent to modify operations (readFE, readEF, cas, or faa) all return the default value specified when the array was declared.
readFE
Blocks until the data element is full, then atomically reads the value and marks it empty.
readFF
Blocks until the data element is full, then atomically reads leaving it full. This allows safe read access of data which may be updated simultaneously. readFF ensures mutual exclusion, and will block if the data is already under a Readers-Writer lock.
readRW, releaseRW
Blocks until the data element is full or already under a Readers-Writer lock, then increments the Readers-Writer reference count. The function emsArray.releaseRW() decrements the reference count, restoring the state to Full if no readers remain.
Node.js and Python emsArray.read(key), emsArray[key].read, x = emsArray.foo
emsArray.readFE(key), emsArray[key].readFE()
emsArray.readFF(key), emsArray[key].readFF()
emsArray.readRW(key), emsArray[key].readRW()
emsArray.releaseRW(key), emsArray[key].releaseRW()
C bool EMSreadRW(const int mmapID, EMSvalueType *key, EMSvalueType *returnValue);
bool EMSreadFF(const int mmapID, EMSvalueType *key, EMSvalueType *returnValue);
bool EMSreadFE(const int mmapID, EMSvalueType *key, EMSvalueType *returnValue);
bool EMSread(const int mmapID, EMSvalueType *key, EMSvalueType *returnValue);
int EMSreleaseRW(const int mmapID, EMSvalueType *key);
ARGUMENTS key <Number | String> key in the EMS array of data to read

RETURNS read__ : < Number | Boolean | String | Undefined | Array | Object >
releaseRW : <Number> Number of pending readers sharing the lock.
EXAMPLES n = histogram.read(3) Read the value in bin 3 of the histogram.
idx = 'foo' word = dictionary.read(idx) word = dictionary[idx].read() word = dictionary.foo Three functionally equivalent ways to read dictionary word at key='foo' in the EMS array called dictionary.
x = arr.readFE(idx) Block until the element at index i is full, atomically read the value and mark it empty.
x = arr.readFF(idx) Block until the element at index i is full, atomically read the value and leave it full.
x = arr.readRW(idx) // Do work using x while it cannot be modified arr.releaseRW(idx) Acquire a shared-exclusive readers-writer lock.
Write EMS Memory
SYNOPSIS Write a JSON value or object to an EMS array.
write
Immediately and unconditionally writes the value to memory. This operation does not honor or modify the full/empty tag status.
writeXE
Unconditionally and atomically writes the value to the data element and marks the element empty.
writeXF
Unconditionally and atomically writes the value to the data element and marks the element full.
writeEF
Blocks until the element is empty, and then atomically writes the value and marks the element full.
Node.js and Python emsArray.write(index, value), emsArray[index].write(value), emsArray.foo = x
emsArray.writeXE(index, value), emsArray[index].writeXE(value)
emsArray.writeXF(index, value), emsArray[index].writeXF(value)
emsArray.writeEF(index, value), emsArray[index].writeEF(value)
C bool EMSwriteXF(int mmapID, EMSvalueType *key, EMSvalueType *value);
bool EMSwriteXE(int mmapID, EMSvalueType *key, EMSvalueType *value);
bool EMSwriteEF(int mmapID, EMSvalueType *key, EMSvalueType *value);
bool EMSwrite(int mmapID, EMSvalueType *key, EMSvalueType *value);
ARGUMENTS index <Number | String | Bool> Index in the EMS array of data to read
value <Any> Primitive value to store in the array at element numbered index.

EXAMPLES idx = 'foo' histogram.write(idx, 0) histogram[idx].write(0) histogram.foo = 0 Initialize the value of histogram['foo'] to 0, ignoring full/empty status.
arr.writeXE(i, undefined) Purge the memory at index i of the EMS array arr.
arr.writeXF(j, 'Mr. Jones') Unconditionally write the string 'Mr. Jones'to the EMS array arr at index j and atomically mark the element full.
arr.writeEF(2, v) Block until the element at index 2 of arr is empty, atomically write the value v and mark the memory full.
Atomic Fetch and Add
Node.js and Python emsArray.faa( index, value ), emsArray[index].faa(value)
C bool EMSfaa(int mmapID, EMSvalueType *key, EMSvalueType *value, EMSvalueType *returnValue);

SYNOPSIS Atomically read the element (scalar or string, not array or object), add the value, and write the new value back to memory. Return the original contents of the memory.

ARGUMENTS index <Number | String> Index of the element in the EMS array emsArray to atomically add to.
value < Number | Boolean | String | Undefined > Value to add to the EMS memory.

RETURNS < Number | Boolean | String |
Undefined >
The stored results are the same type as if a + b were performed.
EXAMPLES oldVal = statistics.faa( timerIdx, elapsed ) oldVal = statistics[timerIdx].faa(elapsed) Return the value in memory before the add operation.
currentSum = arr.faa( index, value ) + value The current value after the atomic operation has occurred.
Atomic Compare and Swap
SYNOPSIS Atomically read the JSON primitive element (scalar or string, not object or array) stored at the array's index, compare the original value to oldValue, and if they are equivalent store the new value. The CAS operation succeeded if the value returned is equivalent to oldValue. CAS will block until the EMS memory is marked full. CAS is the equivalent of atomically performing:
if (arr[idx] == oldValue) then arr[idx] = newValue

Node.js and Python emsArray.cas( index, oldValue, newValue )
emsArray[index].cas(oldValue, newValue)

C bool EMScas(int mmapID, EMSvalueType *key, EMSvalueType *oldValue, EMSvalueType *newValue, EMSvalueType *returnValue);

ARGUMENTS index <Integer | String> Index into the EMS array to update.
oldValue <Number | Boolean | String | Undefined> Value to compare to the value stored in memory.
newValue <Any > Value to store if the value in memory is oldValue

RETURNS < Number | Boolean | String | Undefined > The value in memory when the compare was performed.
EXAMPLES acquiredLock = arr.cas(index, UNLOCKED, LOCKED) == UNLOCKED Evaluates as true if the lock stored at arr[index] was acquired.
oldWord = users[1234].cas('Cooking', 'Eating') Attempt to atomically update user 1234's record from the string 'Cooking' to the string 'Eating'

Composed Array Operations

Composed operations use EMS intrinsics to perform deadlock free atomic operations involving multiple EMS elements. The composed operations use the tags and require data to be full or empty as appropriate for the semantics of the operation.

Transactional Processing of Multiple Elements
SYNOPSIS Lock (by transitioning tags from Full to Empty) one or more EMS elements in a deadlock free way. When multiple locks must be acquired, this function guarantees at least one thread will always make progress. The optional third element indicates the element is read-only and will not be modified by the task while the lock is held. Read-only data is locked using a Readers-Writer lock, permitting additional concurrency.
Performing transactions within transactions can result in deadlock if the thread tries to recursively lock an element.

Node.js and Python ems.tmStart( tmElements )
ems.tmEnd( tmHandle, doCommit )

C C transactions are not presently implemented

ARGUMENTS tmElements <Array> Array identifying which EMS array elements should be locked. Each array element is itself an array naming the EMS array and index/key of the data and an optional Read-Only hint: [ emsArray, index (, isReadOnly) ]
tmHandle <Object> Returned from tmStart(), contains state information needed to abort or commit the transaction.
doCommit <Boolean> Commits the transaction if true, or aborts and rolls back the transaction if false or undefined.

RETURNS ems.tmStart() : < tmHandle > Transaction Handle used later to commit or abort.
EXAMPLES tm = ems.tmStart( [ [users, 'bill', true], [comments, 'george'] ] ) Lock element 'bill' in the users EMS array with a read-only intent, and also lock record 'george' in the comments EMS array.
tm = ems.tmStart( [ [arrA, idxA0], [arrA, idxA1] ] ) Lock indexes idxA0 and idxA1 in array arrA for update to both values.
tm = ems.tmStart([ [arrA, idxA0], [arrA, idxA1, true], [arrB, idxB0, true] ]) Acquire and free locks on the elements in lockList. Element arrA[idxA0] may be modified, but elements arrA[idxA1] and arrB[idxB0] are read-only.
ems.tmEnd( tm, true ) Commit the transaction
Stacks & Queues
SYNOPSIS Append or remove data from a LIFO or FIFO. If the queue or stack is empty, the pop or dequeue operation returns Undefined, which is indistinguishable from an Undefined that was explicitly pushed onto the stack.

Node.js and Python emsArray.push( value )
emsArray.enqueue( value )
emsArray.pop( )
emsArray.dequeue( )

ARGUMENTS value <Any> Value to add to the queue or stack.

RETURNS emsArray.pop(), emsArray.dequeue() : < Any >
emsArray.push() : < Number > emsArray.enqueue() : < Number > The number of elements presently on the stack or queue
EXAMPLES comments.push( "Hello, world" ) Append the string to the EMS array comments
mostRecent = comments.pop() Atomically return the value at the top of the stack.
Look up a key used to map a value
CLASS METHOD emsArray.index2key( index )
SYNOPSIS Convert an index into an EMS array to the key used to map a value to that hashed index. This function can be used to iterate over all the elements of a mapped array.

ARGUMENTS index <Number> Index of the element in the EMS array to get the key for

RETURNS < Any > The key used to map the value which hashed to this index.
Freeing EMS Arrays
CLASS METHOD emsArray.destroy( remove_file )
SYNOPSIS Release the persistent and non-persistent resources associated with an EMS array, alternatively persisting the data if remove_file is false. Implies a barrier.

ARGUMENTS remove_file <Boolean> If true, remove the file, else allow the EMS file to persist.

RETURNS None.
Synchronize EMS Memory to Persistent Storage
CLASS METHOD emsArray.sync( [ index [, nElements] ] )
SYNOPSIS Synchronize the EMS memory with persistent storage.

ARGUMENTS index <String | Number> (Optional, default = entire EMS array) Index of the element in the EMS array to synchronize to disk
nElements <Number> (Optional, only defined if index is also defined, default = 1) Number of sequential indexes, starting with index, that should be synchronized to disk

RETURNS < Boolean > True if memory was successfully synchronized to disk, otherwise false.
EXAMPLES users.sync( userID ) The user's record is committed to disk before the function returns.
TODO Reduce
ARRAY METHOD emsArray.reduce( func )

SYNOPSIS Perform a parallel reduction on the elements of an EMS array.

ARGUMENTS func <Function> Function to combine this element with the partial reduction. Function arguments are func(element, sum), and the function returns a new sum. The arguments and results may be of any type.

RETURNS < Any >
EXAMPLES sum = distances.reduce( function( val, sum ) { return(sum+val) } ) Perform the arithmetic sum on the values in the array.
max = distances.reduce( function( val, currMax ) { return(val > currMax ? tmp : currMax) } ) Find the maximum value in the distance array.
TODO: Permute
ARRAY METHOD emsArray.permute( order )

SYNOPSIS Reorder the array indexes to the ordering specified in the array order. If order contains the same index more than once, the output for those indexes is undefined.

ARGUMENTS order <Array> Integer permutation array.

EXAMPLES arr.permute( order ) Reorder the array arr to the new element ordering.
TODO: Scan
ARRAY METHOD emsArray.scan( func )

SYNOPSIS Perform a parallel prefix operation on the EMS array elements:
a[i] = func(a[i], a[i-1])

ARGUMENTS func <Function> Function to combine this element and the previous element. Function arguments are
func(thisElement, previousElement), and returns a new partial result.

RETURNS < Array >
EXAMPLES partialSums = subtotals.scan( function(val, sum ) { return(sum+val) } ) Return a EMS array with the partial sums in each element.
TODO: Map
ARRAY METHOD emsArray.map( func [, name] )

SYNOPSIS Produce a new EMS array of the same length by invoking func() for each element in the array to produce the corresponding element in the new EMS array.

ARGUMENTS func <Function> Function to perform on each array element. The function is invoked with one argument, the EMS primitive element, and returns a new primitive element.
Persistent filename <String> (Optional, default is non-persistent) If the new mapping should have a persistent backing on a filesystem, this assigns the fully qualified filename.

RETURNS < Number | Boolean | String | Undefined >
EXAMPLES sizescm = sizesInches.map( function(inches) { return(inches * 2.54) } ) Scales each element in the array values from inches to cm, producing a new EMS array with scaled values.
TODO: Filter
ARRAY METHOD emsArray.filter( func [, name] )

SYNOPSIS Produce a new EMS array containing only the elements which evaluate as true when passed as the argument to func(element). The elements of the new array may appear in any order.

ARGUMENTS func <Function> Function to perform on each array element. The function is invoked with one argument, the EMS primitive element, and returns a boolean indicating if the element should be included in the new array.
name <String> (Optional, default is non-persistent) If the new mapping requires persistent backing on a filesystem, the fully qualified filename is defined.

RETURNS < EMS Array >
EXAMPLES bigParts = allParts.filter( function(part) { return(part.size > 100) } ) The new EMS array returned contains only parts whose size is greater than 100.

This browsing experience is Copyright ©2014, Synthetic Semantics and ©2015-2016 Jace A Mogill.