UNPKG

lomath

Version:

Lomath is a tensorial math library extended from lodash.

1,119 lines (789 loc) 127 kB
<!DOCTYPE html> <html> <head> <title>index.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <ul class="sections"> <li id="title"> <div class="annotation"> <h1>index.js</h1> </div> </li> <li id="section-1"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>////////// lomath // //////////</p> </div> </li> <li id="section-2"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>Prepare lodash for extension and export</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> _ = <span class="hljs-built_in">require</span>(<span class="hljs-string">'lodash'</span>).runInContext();</pre></div></div> </li> <li id="section-3"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>the module: lodash extended with math mixins</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> lomath = _.mixin({ AUTHOR: <span class="hljs-string">"kengz"</span>, VERSION: <span class="hljs-string">"0.2.9"</span>,</pre></div></div> </li> <li id="section-4"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>//////////////////////////// Function builder backend // ////////////////////////////</p> </div> </li> <li id="section-5"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>We employ clearer terminologies to distinguish the “depth” or the “dimension” of the objects. In general, we call generic array of depth-N a “N-tensor” or “rank-N tensor”. A scalar is “0-tensor”; a simple array/vector is “1-tensor”, matrix (array of arrays) is “2-tensor”, and so on. A generic function that operates over tensor is built from an atomic function fn taking two scalar arguments. Applying a function into depths of tensor is done via distribution, and evaluating a multi-argument function is done via associativity. sample operation to demonstrate function composition</p> </div> <div class="content"><div class='highlight'><pre> op: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x, y</span>) </span>{ <span class="hljs-keyword">return</span> x + <span class="hljs-string">'*'</span> + y; },</pre></div></div> </li> <li id="section-6"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>distribute a unary function over every scalar in tensor Y;</p> </div> <div class="content"><div class='highlight'><pre> distributeSingle: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, Y</span>) </span>{ <span class="hljs-keyword">if</span> (!(Y <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>)) <span class="hljs-keyword">return</span> fn(Y); <span class="hljs-keyword">var</span> len = Y.length, res = <span class="hljs-built_in">Array</span>(len); <span class="hljs-keyword">while</span> (len--) res[len] = Y[len] <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.distributeSingle(fn, Y[len]) : fn(Y[len]) <span class="hljs-keyword">return</span> res; },</pre></div></div> </li> <li id="section-7"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Distribute fn with left tensor X over right scalar y.</p> </div> <div class="content"><div class='highlight'><pre> distributeLeft: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, X, y</span>) </span>{ <span class="hljs-keyword">var</span> len = X.length, res = <span class="hljs-built_in">Array</span>(len); <span class="hljs-keyword">while</span> (len--) res[len] = X[len] <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.distributeLeft(fn, X[len], y) : fn(X[len], y) <span class="hljs-keyword">return</span> res; },</pre></div></div> </li> <li id="section-8"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Distribute fn with left scalar x over right tensor Y.</p> </div> <div class="content"><div class='highlight'><pre> distributeRight: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, x, Y</span>) </span>{ <span class="hljs-keyword">var</span> len = Y.length, res = <span class="hljs-built_in">Array</span>(len); <span class="hljs-keyword">while</span> (len--) res[len] = Y[len] <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.distributeRight(fn, x, Y[len]) : fn(x, Y[len]) <span class="hljs-keyword">return</span> res; },</pre></div></div> </li> <li id="section-9"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Distribute fn between non-scalar tensors X, Y: pair them up term-wise and calling distribute recursively. If at any depth X and Y have different lengths, recycle if the mod of lengths is 0.</p> </div> <div class="content"><div class='highlight'><pre> distributeBoth: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, X, Y</span>) </span>{ <span class="hljs-keyword">var</span> Xlen = X.length, Ylen = Y.length; <span class="hljs-keyword">if</span> (Xlen % Ylen == <span class="hljs-number">0</span> || Ylen % Xlen == <span class="hljs-number">0</span>) { <span class="hljs-keyword">var</span> res; <span class="hljs-keyword">if</span> (Xlen &gt; Ylen) { res = <span class="hljs-built_in">Array</span>(Xlen); <span class="hljs-keyword">while</span> (Xlen--) res[Xlen] = lomath.distribute(fn, X[Xlen], Y[Xlen % Ylen]); } <span class="hljs-keyword">else</span> { res = <span class="hljs-built_in">Array</span>(Ylen); <span class="hljs-keyword">while</span> (Ylen--) res[Ylen] = lomath.distribute(fn, X[Ylen % Xlen], Y[Ylen]); } <span class="hljs-keyword">return</span> res; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> <span class="hljs-string">"Cannot distribute arrays of different dimensions."</span>; },</pre></div></div> </li> <li id="section-10"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Generic Distribute: Distribute fn between left tensor X and right tensor Y, while preserving the argument-ordering (vital for non-commutative functions). lomath pairs up the tensors term-wise while descending down the depths recursively, until finding a scalar to distributeLeft/Right. Method is at its fastest, and assuming the data depth isn’t too deep (otherwise JS will have troubles with it)</p> </div> <div class="content"><div class='highlight'><pre> distribute: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, X, Y</span>) </span>{ <span class="hljs-keyword">if</span> (X <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) <span class="hljs-keyword">return</span> Y <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.distributeBoth(fn, X, Y) : lomath.distributeLeft(fn, X, Y); <span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> Y <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.distributeRight(fn, X, Y) : fn(X, Y); },</pre></div></div> </li> <li id="section-11"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Generic associate: take the arguments object or array and apply atomic fn (non-tensor) from left to right</p> </div> <div class="content"><div class='highlight'><pre> asso: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, argObj</span>) </span>{ <span class="hljs-keyword">var</span> len = argObj.length, i = <span class="hljs-number">0</span>;</pre></div></div> </li> <li id="section-12"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>optimize arg form based on length or argObj</p> </div> <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> args = len &lt; <span class="hljs-number">3</span> ? argObj : _.toArray(argObj), res = fn(args[i++], args[i++]); <span class="hljs-keyword">while</span> (i &lt; len) res = fn(res, args[i++]); <span class="hljs-keyword">return</span> res; },</pre></div></div> </li> <li id="section-13"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Associate with distributivity: Similar to asso but is for tensor functions; apply atomic fn distributively from left to right. Usage: for applying fn on tensors element-wise if they have matching dimensions.</p> </div> <div class="content"><div class='highlight'><pre> assodist: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, argObj</span>) </span>{ <span class="hljs-keyword">var</span> len = argObj.length, i = <span class="hljs-number">0</span>;</pre></div></div> </li> <li id="section-14"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>optimize arg form based on length or argObj</p> </div> <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> args = len &lt; <span class="hljs-number">3</span> ? argObj : _.toArray(argObj), res = lomath.distribute(fn, args[i++], args[i++]); <span class="hljs-keyword">while</span> (i &lt; len) res = lomath.distribute(fn, res, args[i++]); <span class="hljs-keyword">return</span> res; },</pre></div></div> </li> <li id="section-15"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Future: Future: Future: cross and wedge, need index summation too, matrix mult.</p> </div> </li> <li id="section-16"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>/////////////////// Basic functions // /////////////////// Concat all arguments into single vector by _.flattenDeep</p> </div> <div class="content"><div class='highlight'><pre> c: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> _.flattenDeep(_.toArray(<span class="hljs-built_in">arguments</span>)); },</pre></div></div> </li> <li id="section-17"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>atomic sum: takes in a tensor (any rank) and sum all values</p> </div> <div class="content"><div class='highlight'><pre> a_sum: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{</pre></div></div> </li> <li id="section-18"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>actual function call; recurse if need to</p> </div> <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> total = <span class="hljs-number">0</span>, len = T.length; <span class="hljs-keyword">while</span> (len--) total += (T[len] <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.a_sum(T[len], <span class="hljs-number">0</span>) : T[len]) <span class="hljs-keyword">return</span> total; },</pre></div></div> </li> <li id="section-19"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>sum all values in all arguments</p> </div> <div class="content"><div class='highlight'><pre> sum: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">var</span> res = <span class="hljs-number">0</span>; <span class="hljs-keyword">var</span> len = <span class="hljs-built_in">arguments</span>.length; <span class="hljs-keyword">while</span> (len--) res += (<span class="hljs-built_in">arguments</span>[len] <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.a_sum(<span class="hljs-built_in">arguments</span>[len]) : <span class="hljs-built_in">arguments</span>[len]) <span class="hljs-keyword">return</span> res; }, fsum: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T, fn</span>) </span>{ <span class="hljs-keyword">var</span> sum = <span class="hljs-number">0</span>; <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; T.length; i++) sum += fn(T, i); <span class="hljs-keyword">return</span> sum; },</pre></div></div> </li> <li id="section-20"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>atomic prod, analogue to a_sum. Multiply all values in a tensor</p> </div> <div class="content"><div class='highlight'><pre> a_prod: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{</pre></div></div> </li> <li id="section-21"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>actual function call; recurse if need to</p> </div> <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> total = <span class="hljs-number">1</span>, len = T.length; <span class="hljs-keyword">while</span> (len--) total *= (T[len] <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.a_prod(T[len], <span class="hljs-number">1</span>) : T[len]) <span class="hljs-keyword">return</span> total; },</pre></div></div> </li> <li id="section-22"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>product of all values in all arguments</p> </div> <div class="content"><div class='highlight'><pre> prod: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">var</span> res = <span class="hljs-number">1</span>, len = <span class="hljs-built_in">arguments</span>.length; <span class="hljs-keyword">while</span> (len--) res *= (<span class="hljs-built_in">arguments</span>[len] <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span> ? lomath.a_prod(<span class="hljs-built_in">arguments</span>[len]) : <span class="hljs-built_in">arguments</span>[len]) <span class="hljs-keyword">return</span> res; },</pre></div></div> </li> <li id="section-23"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>atomic add: add two scalars x, y.</p> </div> <div class="content"><div class='highlight'><pre> a_add: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x, y</span>) </span>{ <span class="hljs-keyword">return</span> x + y; },</pre></div></div> </li> <li id="section-24"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>add all tensor arguments element-wise/distributively and associatively</p> </div> <div class="content"><div class='highlight'><pre> add: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{</pre></div></div> </li> <li id="section-25"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>sample call pattern: pass whole args</p> </div> <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> lomath.assodist(lomath.a_add, <span class="hljs-built_in">arguments</span>); },</pre></div></div> </li> <li id="section-26"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>atomic subtract</p> </div> <div class="content"><div class='highlight'><pre> a_subtract: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x, y</span>) </span>{ <span class="hljs-keyword">return</span> x - y; },</pre></div></div> </li> <li id="section-27"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>subtract all tensor arguments element-wise/distributively and associatively</p> </div> <div class="content"><div class='highlight'><pre> subtract: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> lomath.assodist(lomath.a_subtract, <span class="hljs-built_in">arguments</span>); },</pre></div></div> </li> <li id="section-28"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>atomic multiply</p> </div> <div class="content"><div class='highlight'><pre> a_multiply: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x, y</span>) </span>{ <span class="hljs-keyword">return</span> x * y; },</pre></div></div> </li> <li id="section-29"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>multiply all tensor arguments element-wise/distributively and associatively Note: lomath is generic; is different from matrix multiplication</p> </div> <div class="content"><div class='highlight'><pre> multiply: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> lomath.assodist(lomath.a_multiply, <span class="hljs-built_in">arguments</span>); },</pre></div></div> </li> <li id="section-30"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>atomic divide</p> </div> <div class="content"><div class='highlight'><pre> a_divide: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x, y</span>) </span>{ <span class="hljs-keyword">return</span> x / y; },</pre></div></div> </li> <li id="section-31"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>divide all tensor arguments element-wise/distributively and associatively</p> </div> <div class="content"><div class='highlight'><pre> divide: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> lomath.assodist(lomath.a_divide, <span class="hljs-built_in">arguments</span>); },</pre></div></div> </li> <li id="section-32"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-32">&#182;</a> </div> <p>atomic log. Use base e by default</p> </div> <div class="content"><div class='highlight'><pre> a_log: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x, base</span>) </span>{ <span class="hljs-keyword">return</span> base == <span class="hljs-literal">undefined</span> ? <span class="hljs-built_in">Math</span>.log(x) : <span class="hljs-built_in">Math</span>.log(x) / <span class="hljs-built_in">Math</span>.log(base); },</pre></div></div> </li> <li id="section-33"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>take the log of tensor T to the n element-wise</p> </div> <div class="content"><div class='highlight'><pre> log: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T, base</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distribute(lomath.a_log, T, base); },</pre></div></div> </li> <li id="section-34"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>atomic square</p> </div> <div class="content"><div class='highlight'><pre> a_square: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x * x; }, square: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(lomath.a_square, T); },</pre></div></div> </li> <li id="section-35"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>atomic root</p> </div> <div class="content"><div class='highlight'><pre> a_root: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x, base</span>) </span>{ <span class="hljs-keyword">var</span> n = base == <span class="hljs-literal">undefined</span> ? <span class="hljs-number">2</span> : base; <span class="hljs-keyword">return</span> n % <span class="hljs-number">2</span> ?</pre></div></div> </li> <li id="section-36"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-36">&#182;</a> </div> <p>if odd power</p> </div> <div class="content"><div class='highlight'><pre> <span class="hljs-built_in">Math</span>.sign(x) * <span class="hljs-built_in">Math</span>.pow(<span class="hljs-built_in">Math</span>.abs(x), <span class="hljs-number">1</span> / n) : <span class="hljs-built_in">Math</span>.pow(x, <span class="hljs-number">1</span> / n); },</pre></div></div> </li> <li id="section-37"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-37">&#182;</a> </div> <p>take the n-th root of tensor T element-wise</p> </div> <div class="content"><div class='highlight'><pre> root: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T, n</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distribute(lomath.a_root, T, n); },</pre></div></div> </li> <li id="section-38"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-38">&#182;</a> </div> <p>atomic logistic</p> </div> <div class="content"><div class='highlight'><pre> a_logistic: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">z</span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-number">1</span> / (<span class="hljs-number">1</span> + <span class="hljs-built_in">Math</span>.exp(-z)) }, logistic: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(lomath.a_logistic, T); },</pre></div></div> </li> <li id="section-39"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-39">&#182;</a> </div> <p>////////////////// Basic checkers // ////////////////// check if x is in range set by left, right</p> </div> <div class="content"><div class='highlight'><pre> inRange: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">left, right, x</span>) </span>{ <span class="hljs-keyword">return</span> left - <span class="hljs-number">1</span> &lt; x &amp;&amp; x &lt; right + <span class="hljs-number">1</span>; },</pre></div></div> </li> <li id="section-40"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-40">&#182;</a> </div> <p>check if x is an integer</p> </div> <div class="content"><div class='highlight'><pre> isInteger: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x == <span class="hljs-built_in">Math</span>.floor(x); },</pre></div></div> </li> <li id="section-41"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>check if x is a double</p> </div> <div class="content"><div class='highlight'><pre> isDouble: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x != <span class="hljs-built_in">Math</span>.floor(x); },</pre></div></div> </li> <li id="section-42"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>check if x is positive</p> </div> <div class="content"><div class='highlight'><pre> isPositive: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x &gt; <span class="hljs-number">0</span>; },</pre></div></div> </li> <li id="section-43"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-43">&#182;</a> </div> <p>check if x less than or eq to 0</p> </div> <div class="content"><div class='highlight'><pre> nonPositive: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> !(x &gt; <span class="hljs-number">0</span>); },</pre></div></div> </li> <li id="section-44"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-44">&#182;</a> </div> <p>check if x is negative</p> </div> <div class="content"><div class='highlight'><pre> isNegative: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x &lt; <span class="hljs-number">0</span>; },</pre></div></div> </li> <li id="section-45"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-45">&#182;</a> </div> <p>check if x greater than or eq to 0</p> </div> <div class="content"><div class='highlight'><pre> nonNegative: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> !(x &lt; <span class="hljs-number">0</span>); }, isZero: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x == <span class="hljs-number">0</span>; }, nonZero: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x != <span class="hljs-number">0</span>; }, parity: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{ <span class="hljs-keyword">return</span> x % <span class="hljs-number">2</span> ? <span class="hljs-number">-1</span> : <span class="hljs-number">1</span>; },</pre></div></div> </li> <li id="section-46"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-46">&#182;</a> </div> <p>check if all tensor entries are of the same sign, with the specified sign function</p> </div> <div class="content"><div class='highlight'><pre> sameSig: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T, sigFn</span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-built_in">Boolean</span>(lomath.prod(lomath.distributeSingle(sigFn, T))); },</pre></div></div> </li> <li id="section-47"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-47">&#182;</a> </div> <p>check if all tensor entries are of the same sign, with the specified sign function</p> </div> <div class="content"><div class='highlight'><pre> deepEqual: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T, S</span>) </span>{ <span class="hljs-keyword">if</span> (T.length != S.length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; <span class="hljs-keyword">var</span> Left = T, Right = S; <span class="hljs-keyword">if</span> (!lomath.isFlat(T)) { Left = _.flattenDeep(T); Right = _.flattenDeep(S); }; <span class="hljs-keyword">var</span> Llen = Left.length, Rlen = Right.length; <span class="hljs-keyword">while</span> (Llen--) { <span class="hljs-keyword">if</span> (Left[Llen] != Right[Llen]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; } <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; },</pre></div></div> </li> <li id="section-48"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-48">&#182;</a> </div> <p>//////////////////////////////////////// Unary functions from JS Math object, // //////////////////////////////////////// wrapped to function with generic tensor</p> </div> <div class="content"><div class='highlight'><pre> abs: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.abs, T); }, acos: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.acos, T); }, acosh: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.acosh, T); }, asin: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.asin, T); }, asinh: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.asinh, T); }, atan: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.atan, T); }, atanh: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.atanh, T); }, ceil: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.ceil, T); }, cos: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.cos, T); }, cosh: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.cosh, T); }, exp: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.exp, T); }, floor: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.floor, T); }, log10: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.log10, T); }, log1p: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.log1p, T); }, log2: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.log2, T); }, round: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.round, T); }, pow: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T, n</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distribute(<span class="hljs-built_in">Math</span>.pow, T, n); }, sign: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.sign, T); }, sin: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.sin, T); }, sinh: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.sinh, T); }, sqrt: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.sqrt, T); }, tan: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.tan, T); }, tanh: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.tanh, T); }, trunc: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">T</span>) </span>{ <span class="hljs-keyword">return</span> lomath.distributeSingle(<span class="hljs-built_in">Math</span>.trunc, T); },</pre></div></div> </li> <li id="section-49"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-49">&#182;</a> </div> <p>/////////////////// Regex functions // /////////////////// return a function that matches regex, e.g. matchRegex(/red/)(‘red Apple’) returns true</p> </div> <div class="content"><div class='highlight'><pre> reMatch: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">regex</span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">str</span>) </span>{ <span class="hljs-keyword">if</span> (str != <span class="hljs-literal">undefined</span>) <span class="hljs-keyword">return</span> str.search(regex) != <span class="hljs-number">-1</span>; } },</pre></div></div> </li> <li id="section-50"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-50">&#182;</a> </div> <p>negation of reMatch</p> </div> <div class="content"><div class='highlight'><pre> reNotMatch: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">regex</span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">str</span>) </span>{ <span class="hljs-keyword">if</span> (str != <span class="hljs-literal">undefined</span>) <span class="hljs-keyword">return</span> str.search(regex) == <span class="hljs-number">-1</span>; } },</pre></div></div> </li> <li id="section-51"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>return the string matched by regex</p> </div> <div class="content"><div class='highlight'><pre> reGet: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">regex</span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">str</span>) </span>{ <span class="hljs-keyword">if</span> (str != <span class="hljs-literal">undefined</span>) { <span class="hljs-keyword">var</span> matched = str.match(regex); <span class="hljs-keyword">return</span> matched == <span class="hljs-literal">null</span> ? <span class="hljs-literal">null</span> : matched[<span class="hljs-number">0</span>]; } } },</pre></div></div> </li> <li id="section-52"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p>wrap a regex into string for regex set operation</p> </div> <div class="content"><div class='highlight'><pre> reWrap: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">reg</span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-string">'(?:'</span> + <span class="hljs-built_in">String</span>(reg).replace(<span class="hljs-regexp">/\//g</span>, <span class="hljs-string">''</span>) + <span class="hljs-string">')'</span> },</pre></div></div> </li> <li id="section-53"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-53">&#182;</a> </div> <p>return a single regex as the “AND” of all arg regex’s</p> </div> <div class="content"><div class='highlight'><pre> reAnd: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(_.map(_.toArray(<span class="hljs-built_in">arguments</span>), lomath.reWrap).join(<span class="hljs-string">''</span>)); },</pre></div></div> </li> <li id="section-54"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-54">&#182;</a> </div> <p>return a function that matches all(AND) of the regexs</p> </div> <div class="content"><div class='highlight'><pre> reAndMatch: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">return</span> lomath.reMatch(lomath.reAnd.apply(<span class="hljs-literal">null</span>, <span class="hljs-built_in">arguments</span>)); },</pre></div></div> </li> <li id="section-55"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-55">&#182;</a> </div> <p>return a single regex as the “OR” of all arg regex’s</p> </div>