This repository has been archived by the owner. It is now read-only.
Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| //import Native.List // | |
| var _elm_lang$core$Native_Array = function() { | |
| // A RRB-Tree has two distinct data types. | |
| // Leaf -> "height" is always 0 | |
| // "table" is an array of elements | |
| // Node -> "height" is always greater than 0 | |
| // "table" is an array of child nodes | |
| // "lengths" is an array of accumulated lengths of the child nodes | |
| // M is the maximal table size. 32 seems fast. E is the allowed increase | |
| // of search steps when concatting to find an index. Lower values will | |
| // decrease balancing, but will increase search steps. | |
| var M = 32; | |
| var E = 2; | |
| // An empty array. | |
| var empty = { | |
| ctor: '_Array', | |
| height: 0, | |
| table: [] | |
| }; | |
| function get(i, array) | |
| { | |
| if (i < 0 || i >= length(array)) | |
| { | |
| throw new Error( | |
| 'Index ' + i + ' is out of range. Check the length of ' + | |
| 'your array first or use getMaybe or getWithDefault.'); | |
| } | |
| return unsafeGet(i, array); | |
| } | |
| function unsafeGet(i, array) | |
| { | |
| for (var x = array.height; x > 0; x--) | |
| { | |
| var slot = i >> (x * 5); | |
| while (array.lengths[slot] <= i) | |
| { | |
| slot++; | |
| } | |
| if (slot > 0) | |
| { | |
| i -= array.lengths[slot - 1]; | |
| } | |
| array = array.table[slot]; | |
| } | |
| return array.table[i]; | |
| } | |
| // Sets the value at the index i. Only the nodes leading to i will get | |
| // copied and updated. | |
| function set(i, item, array) | |
| { | |
| if (i < 0 || length(array) <= i) | |
| { | |
| return array; | |
| } | |
| return unsafeSet(i, item, array); | |
| } | |
| function unsafeSet(i, item, array) | |
| { | |
| array = nodeCopy(array); | |
| if (array.height === 0) | |
| { | |
| array.table[i] = item; | |
| } | |
| else | |
| { | |
| var slot = getSlot(i, array); | |
| if (slot > 0) | |
| { | |
| i -= array.lengths[slot - 1]; | |
| } | |
| array.table[slot] = unsafeSet(i, item, array.table[slot]); | |
| } | |
| return array; | |
| } | |
| function initialize(len, f) | |
| { | |
| if (len <= 0) | |
| { | |
| return empty; | |
| } | |
| var h = Math.floor( Math.log(len) / Math.log(M) ); | |
| return initialize_(f, h, 0, len); | |
| } | |
| function initialize_(f, h, from, to) | |
| { | |
| if (h === 0) | |
| { | |
| var table = new Array((to - from) % (M + 1)); | |
| for (var i = 0; i < table.length; i++) | |
| { | |
| table[i] = f(from + i); | |
| } | |
| return { | |
| ctor: '_Array', | |
| height: 0, | |
| table: table | |
| }; | |
| } | |
| var step = Math.pow(M, h); | |
| var table = new Array(Math.ceil((to - from) / step)); | |
| var lengths = new Array(table.length); | |
| for (var i = 0; i < table.length; i++) | |
| { | |
| table[i] = initialize_(f, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); | |
| lengths[i] = length(table[i]) + (i > 0 ? lengths[i-1] : 0); | |
| } | |
| return { | |
| ctor: '_Array', | |
| height: h, | |
| table: table, | |
| lengths: lengths | |
| }; | |
| } | |
| function fromList(list) | |
| { | |
| if (list.ctor === '[]') | |
| { | |
| return empty; | |
| } | |
| // Allocate M sized blocks (table) and write list elements to it. | |
| var table = new Array(M); | |
| var nodes = []; | |
| var i = 0; | |
| while (list.ctor !== '[]') | |
| { | |
| table[i] = list._0; | |
| list = list._1; | |
| i++; | |
| // table is full, so we can push a leaf containing it into the | |
| // next node. | |
| if (i === M) | |
| { | |
| var leaf = { | |
| ctor: '_Array', | |
| height: 0, | |
| table: table | |
| }; | |
| fromListPush(leaf, nodes); | |
| table = new Array(M); | |
| i = 0; | |
| } | |
| } | |
| // Maybe there is something left on the table. | |
| if (i > 0) | |
| { | |
| var leaf = { | |
| ctor: '_Array', | |
| height: 0, | |
| table: table.splice(0, i) | |
| }; | |
| fromListPush(leaf, nodes); | |
| } | |
| // Go through all of the nodes and eventually push them into higher nodes. | |
| for (var h = 0; h < nodes.length - 1; h++) | |
| { | |
| if (nodes[h].table.length > 0) | |
| { | |
| fromListPush(nodes[h], nodes); | |
| } | |
| } | |
| var head = nodes[nodes.length - 1]; | |
| if (head.height > 0 && head.table.length === 1) | |
| { | |
| return head.table[0]; | |
| } | |
| else | |
| { | |
| return head; | |
| } | |
| } | |
| // Push a node into a higher node as a child. | |
| function fromListPush(toPush, nodes) | |
| { | |
| var h = toPush.height; | |
| // Maybe the node on this height does not exist. | |
| if (nodes.length === h) | |
| { | |
| var node = { | |
| ctor: '_Array', | |
| height: h + 1, | |
| table: [], | |
| lengths: [] | |
| }; | |
| nodes.push(node); | |
| } | |
| nodes[h].table.push(toPush); | |
| var len = length(toPush); | |
| if (nodes[h].lengths.length > 0) | |
| { | |
| len += nodes[h].lengths[nodes[h].lengths.length - 1]; | |
| } | |
| nodes[h].lengths.push(len); | |
| if (nodes[h].table.length === M) | |
| { | |
| fromListPush(nodes[h], nodes); | |
| nodes[h] = { | |
| ctor: '_Array', | |
| height: h + 1, | |
| table: [], | |
| lengths: [] | |
| }; | |
| } | |
| } | |
| // Pushes an item via push_ to the bottom right of a tree. | |
| function push(item, a) | |
| { | |
| var pushed = push_(item, a); | |
| if (pushed !== null) | |
| { | |
| return pushed; | |
| } | |
| var newTree = create(item, a.height); | |
| return siblise(a, newTree); | |
| } | |
| // Recursively tries to push an item to the bottom-right most | |
| // tree possible. If there is no space left for the item, | |
| // null will be returned. | |
| function push_(item, a) | |
| { | |
| // Handle resursion stop at leaf level. | |
| if (a.height === 0) | |
| { | |
| if (a.table.length < M) | |
| { | |
| var newA = { | |
| ctor: '_Array', | |
| height: 0, | |
| table: a.table.slice() | |
| }; | |
| newA.table.push(item); | |
| return newA; | |
| } | |
| else | |
| { | |
| return null; | |
| } | |
| } | |
| // Recursively push | |
| var pushed = push_(item, botRight(a)); | |
| // There was space in the bottom right tree, so the slot will | |
| // be updated. | |
| if (pushed !== null) | |
| { | |
| var newA = nodeCopy(a); | |
| newA.table[newA.table.length - 1] = pushed; | |
| newA.lengths[newA.lengths.length - 1]++; | |
| return newA; | |
| } | |
| // When there was no space left, check if there is space left | |
| // for a new slot with a tree which contains only the item | |
| // at the bottom. | |
| if (a.table.length < M) | |
| { | |
| var newSlot = create(item, a.height - 1); | |
| var newA = nodeCopy(a); | |
| newA.table.push(newSlot); | |
| newA.lengths.push(newA.lengths[newA.lengths.length - 1] + length(newSlot)); | |
| return newA; | |
| } | |
| else | |
| { | |
| return null; | |
| } | |
| } | |
| // Converts an array into a list of elements. | |
| function toList(a) | |
| { | |
| return toList_(_elm_lang$core$Native_List.Nil, a); | |
| } | |
| function toList_(list, a) | |
| { | |
| for (var i = a.table.length - 1; i >= 0; i--) | |
| { | |
| list = | |
| a.height === 0 | |
| ? _elm_lang$core$Native_List.Cons(a.table[i], list) | |
| : toList_(list, a.table[i]); | |
| } | |
| return list; | |
| } | |
| // Maps a function over the elements of an array. | |
| function map(f, a) | |
| { | |
| var newA = { | |
| ctor: '_Array', | |
| height: a.height, | |
| table: new Array(a.table.length) | |
| }; | |
| if (a.height > 0) | |
| { | |
| newA.lengths = a.lengths; | |
| } | |
| for (var i = 0; i < a.table.length; i++) | |
| { | |
| newA.table[i] = | |
| a.height === 0 | |
| ? f(a.table[i]) | |
| : map(f, a.table[i]); | |
| } | |
| return newA; | |
| } | |
| // Maps a function over the elements with their index as first argument. | |
| function indexedMap(f, a) | |
| { | |
| return indexedMap_(f, a, 0); | |
| } | |
| function indexedMap_(f, a, from) | |
| { | |
| var newA = { | |
| ctor: '_Array', | |
| height: a.height, | |
| table: new Array(a.table.length) | |
| }; | |
| if (a.height > 0) | |
| { | |
| newA.lengths = a.lengths; | |
| } | |
| for (var i = 0; i < a.table.length; i++) | |
| { | |
| newA.table[i] = | |
| a.height === 0 | |
| ? A2(f, from + i, a.table[i]) | |
| : indexedMap_(f, a.table[i], i == 0 ? from : from + a.lengths[i - 1]); | |
| } | |
| return newA; | |
| } | |
| function foldl(f, b, a) | |
| { | |
| if (a.height === 0) | |
| { | |
| for (var i = 0; i < a.table.length; i++) | |
| { | |
| b = A2(f, a.table[i], b); | |
| } | |
| } | |
| else | |
| { | |
| for (var i = 0; i < a.table.length; i++) | |
| { | |
| b = foldl(f, b, a.table[i]); | |
| } | |
| } | |
| return b; | |
| } | |
| function foldr(f, b, a) | |
| { | |
| if (a.height === 0) | |
| { | |
| for (var i = a.table.length; i--; ) | |
| { | |
| b = A2(f, a.table[i], b); | |
| } | |
| } | |
| else | |
| { | |
| for (var i = a.table.length; i--; ) | |
| { | |
| b = foldr(f, b, a.table[i]); | |
| } | |
| } | |
| return b; | |
| } | |
| // TODO: currently, it slices the right, then the left. This can be | |
| // optimized. | |
| function slice(from, to, a) | |
| { | |
| if (from < 0) | |
| { | |
| from += length(a); | |
| } | |
| if (to < 0) | |
| { | |
| to += length(a); | |
| } | |
| return sliceLeft(from, sliceRight(to, a)); | |
| } | |
| function sliceRight(to, a) | |
| { | |
| if (to === length(a)) | |
| { | |
| return a; | |
| } | |
| // Handle leaf level. | |
| if (a.height === 0) | |
| { | |
| var newA = { ctor:'_Array', height:0 }; | |
| newA.table = a.table.slice(0, to); | |
| return newA; | |
| } | |
| // Slice the right recursively. | |
| var right = getSlot(to, a); | |
| var sliced = sliceRight(to - (right > 0 ? a.lengths[right - 1] : 0), a.table[right]); | |
| // Maybe the a node is not even needed, as sliced contains the whole slice. | |
| if (right === 0) | |
| { | |
| return sliced; | |
| } | |
| // Create new node. | |
| var newA = { | |
| ctor: '_Array', | |
| height: a.height, | |
| table: a.table.slice(0, right), | |
| lengths: a.lengths.slice(0, right) | |
| }; | |
| if (sliced.table.length > 0) | |
| { | |
| newA.table[right] = sliced; | |
| newA.lengths[right] = length(sliced) + (right > 0 ? newA.lengths[right - 1] : 0); | |
| } | |
| return newA; | |
| } | |
| function sliceLeft(from, a) | |
| { | |
| if (from === 0) | |
| { | |
| return a; | |
| } | |
| // Handle leaf level. | |
| if (a.height === 0) | |
| { | |
| var newA = { ctor:'_Array', height:0 }; | |
| newA.table = a.table.slice(from, a.table.length + 1); | |
| return newA; | |
| } | |
| // Slice the left recursively. | |
| var left = getSlot(from, a); | |
| var sliced = sliceLeft(from - (left > 0 ? a.lengths[left - 1] : 0), a.table[left]); | |
| // Maybe the a node is not even needed, as sliced contains the whole slice. | |
| if (left === a.table.length - 1) | |
| { | |
| return sliced; | |
| } | |
| // Create new node. | |
| var newA = { | |
| ctor: '_Array', | |
| height: a.height, | |
| table: a.table.slice(left, a.table.length + 1), | |
| lengths: new Array(a.table.length - left) | |
| }; | |
| newA.table[0] = sliced; | |
| var len = 0; | |
| for (var i = 0; i < newA.table.length; i++) | |
| { | |
| len += length(newA.table[i]); | |
| newA.lengths[i] = len; | |
| } | |
| return newA; | |
| } | |
| // Appends two trees. | |
| function append(a,b) | |
| { | |
| if (a.table.length === 0) | |
| { | |
| return b; | |
| } | |
| if (b.table.length === 0) | |
| { | |
| return a; | |
| } | |
| var c = append_(a, b); | |
| // Check if both nodes can be crunshed together. | |
| if (c[0].table.length + c[1].table.length <= M) | |
| { | |
| if (c[0].table.length === 0) | |
| { | |
| return c[1]; | |
| } | |
| if (c[1].table.length === 0) | |
| { | |
| return c[0]; | |
| } | |
| // Adjust .table and .lengths | |
| c[0].table = c[0].table.concat(c[1].table); | |
| if (c[0].height > 0) | |
| { | |
| var len = length(c[0]); | |
| for (var i = 0; i < c[1].lengths.length; i++) | |
| { | |
| c[1].lengths[i] += len; | |
| } | |
| c[0].lengths = c[0].lengths.concat(c[1].lengths); | |
| } | |
| return c[0]; | |
| } | |
| if (c[0].height > 0) | |
| { | |
| var toRemove = calcToRemove(a, b); | |
| if (toRemove > E) | |
| { | |
| c = shuffle(c[0], c[1], toRemove); | |
| } | |
| } | |
| return siblise(c[0], c[1]); | |
| } | |
| // Returns an array of two nodes; right and left. One node _may_ be empty. | |
| function append_(a, b) | |
| { | |
| if (a.height === 0 && b.height === 0) | |
| { | |
| return [a, b]; | |
| } | |
| if (a.height !== 1 || b.height !== 1) | |
| { | |
| if (a.height === b.height) | |
| { | |
| a = nodeCopy(a); | |
| b = nodeCopy(b); | |
| var appended = append_(botRight(a), botLeft(b)); | |
| insertRight(a, appended[1]); | |
| insertLeft(b, appended[0]); | |
| } | |
| else if (a.height > b.height) | |
| { | |
| a = nodeCopy(a); | |
| var appended = append_(botRight(a), b); | |
| insertRight(a, appended[0]); | |
| b = parentise(appended[1], appended[1].height + 1); | |
| } | |
| else | |
| { | |
| b = nodeCopy(b); | |
| var appended = append_(a, botLeft(b)); | |
| var left = appended[0].table.length === 0 ? 0 : 1; | |
| var right = left === 0 ? 1 : 0; | |
| insertLeft(b, appended[left]); | |
| a = parentise(appended[right], appended[right].height + 1); | |
| } | |
| } | |
| // Check if balancing is needed and return based on that. | |
| if (a.table.length === 0 || b.table.length === 0) | |
| { | |
| return [a, b]; | |
| } | |
| var toRemove = calcToRemove(a, b); | |
| if (toRemove <= E) | |
| { | |
| return [a, b]; | |
| } | |
| return shuffle(a, b, toRemove); | |
| } | |
| // Helperfunctions for append_. Replaces a child node at the side of the parent. | |
| function insertRight(parent, node) | |
| { | |
| var index = parent.table.length - 1; | |
| parent.table[index] = node; | |
| parent.lengths[index] = length(node); | |
| parent.lengths[index] += index > 0 ? parent.lengths[index - 1] : 0; | |
| } | |
| function insertLeft(parent, node) | |
| { | |
| if (node.table.length > 0) | |
| { | |
| parent.table[0] = node; | |
| parent.lengths[0] = length(node); | |
| var len = length(parent.table[0]); | |
| for (var i = 1; i < parent.lengths.length; i++) | |
| { | |
| len += length(parent.table[i]); | |
| parent.lengths[i] = len; | |
| } | |
| } | |
| else | |
| { | |
| parent.table.shift(); | |
| for (var i = 1; i < parent.lengths.length; i++) | |
| { | |
| parent.lengths[i] = parent.lengths[i] - parent.lengths[0]; | |
| } | |
| parent.lengths.shift(); | |
| } | |
| } | |
| // Returns the extra search steps for E. Refer to the paper. | |
| function calcToRemove(a, b) | |
| { | |
| var subLengths = 0; | |
| for (var i = 0; i < a.table.length; i++) | |
| { | |
| subLengths += a.table[i].table.length; | |
| } | |
| for (var i = 0; i < b.table.length; i++) | |
| { | |
| subLengths += b.table[i].table.length; | |
| } | |
| var toRemove = a.table.length + b.table.length; | |
| return toRemove - (Math.floor((subLengths - 1) / M) + 1); | |
| } | |
| // get2, set2 and saveSlot are helpers for accessing elements over two arrays. | |
| function get2(a, b, index) | |
| { | |
| return index < a.length | |
| ? a[index] | |
| : b[index - a.length]; | |
| } | |
| function set2(a, b, index, value) | |
| { | |
| if (index < a.length) | |
| { | |
| a[index] = value; | |
| } | |
| else | |
| { | |
| b[index - a.length] = value; | |
| } | |
| } | |
| function saveSlot(a, b, index, slot) | |
| { | |
| set2(a.table, b.table, index, slot); | |
| var l = (index === 0 || index === a.lengths.length) | |
| ? 0 | |
| : get2(a.lengths, a.lengths, index - 1); | |
| set2(a.lengths, b.lengths, index, l + length(slot)); | |
| } | |
| // Creates a node or leaf with a given length at their arrays for perfomance. | |
| // Is only used by shuffle. | |
| function createNode(h, length) | |
| { | |
| if (length < 0) | |
| { | |
| length = 0; | |
| } | |
| var a = { | |
| ctor: '_Array', | |
| height: h, | |
| table: new Array(length) | |
| }; | |
| if (h > 0) | |
| { | |
| a.lengths = new Array(length); | |
| } | |
| return a; | |
| } | |
| // Returns an array of two balanced nodes. | |
| function shuffle(a, b, toRemove) | |
| { | |
| var newA = createNode(a.height, Math.min(M, a.table.length + b.table.length - toRemove)); | |
| var newB = createNode(a.height, newA.table.length - (a.table.length + b.table.length - toRemove)); | |
| // Skip the slots with size M. More precise: copy the slot references | |
| // to the new node | |
| var read = 0; | |
| while (get2(a.table, b.table, read).table.length % M === 0) | |
| { | |
| set2(newA.table, newB.table, read, get2(a.table, b.table, read)); | |
| set2(newA.lengths, newB.lengths, read, get2(a.lengths, b.lengths, read)); | |
| read++; | |
| } | |
| // Pulling items from left to right, caching in a slot before writing | |
| // it into the new nodes. | |
| var write = read; | |
| var slot = new createNode(a.height - 1, 0); | |
| var from = 0; | |
| // If the current slot is still containing data, then there will be at | |
| // least one more write, so we do not break this loop yet. | |
| while (read - write - (slot.table.length > 0 ? 1 : 0) < toRemove) | |
| { | |
| // Find out the max possible items for copying. | |
| var source = get2(a.table, b.table, read); | |
| var to = Math.min(M - slot.table.length, source.table.length); | |
| // Copy and adjust size table. | |
| slot.table = slot.table.concat(source.table.slice(from, to)); | |
| if (slot.height > 0) | |
| { | |
| var len = slot.lengths.length; | |
| for (var i = len; i < len + to - from; i++) | |
| { | |
| slot.lengths[i] = length(slot.table[i]); | |
| slot.lengths[i] += (i > 0 ? slot.lengths[i - 1] : 0); | |
| } | |
| } | |
| from += to; | |
| // Only proceed to next slots[i] if the current one was | |
| // fully copied. | |
| if (source.table.length <= to) | |
| { | |
| read++; from = 0; | |
| } | |
| // Only create a new slot if the current one is filled up. | |
| if (slot.table.length === M) | |
| { | |
| saveSlot(newA, newB, write, slot); | |
| slot = createNode(a.height - 1, 0); | |
| write++; | |
| } | |
| } | |
| // Cleanup after the loop. Copy the last slot into the new nodes. | |
| if (slot.table.length > 0) | |
| { | |
| saveSlot(newA, newB, write, slot); | |
| write++; | |
| } | |
| // Shift the untouched slots to the left | |
| while (read < a.table.length + b.table.length ) | |
| { | |
| saveSlot(newA, newB, write, get2(a.table, b.table, read)); | |
| read++; | |
| write++; | |
| } | |
| return [newA, newB]; | |
| } | |
| // Navigation functions | |
| function botRight(a) | |
| { | |
| return a.table[a.table.length - 1]; | |
| } | |
| function botLeft(a) | |
| { | |
| return a.table[0]; | |
| } | |
| // Copies a node for updating. Note that you should not use this if | |
| // only updating only one of "table" or "lengths" for performance reasons. | |
| function nodeCopy(a) | |
| { | |
| var newA = { | |
| ctor: '_Array', | |
| height: a.height, | |
| table: a.table.slice() | |
| }; | |
| if (a.height > 0) | |
| { | |
| newA.lengths = a.lengths.slice(); | |
| } | |
| return newA; | |
| } | |
| // Returns how many items are in the tree. | |
| function length(array) | |
| { | |
| if (array.height === 0) | |
| { | |
| return array.table.length; | |
| } | |
| else | |
| { | |
| return array.lengths[array.lengths.length - 1]; | |
| } | |
| } | |
| // Calculates in which slot of "table" the item probably is, then | |
| // find the exact slot via forward searching in "lengths". Returns the index. | |
| function getSlot(i, a) | |
| { | |
| var slot = i >> (5 * a.height); | |
| while (a.lengths[slot] <= i) | |
| { | |
| slot++; | |
| } | |
| return slot; | |
| } | |
| // Recursively creates a tree with a given height containing | |
| // only the given item. | |
| function create(item, h) | |
| { | |
| if (h === 0) | |
| { | |
| return { | |
| ctor: '_Array', | |
| height: 0, | |
| table: [item] | |
| }; | |
| } | |
| return { | |
| ctor: '_Array', | |
| height: h, | |
| table: [create(item, h - 1)], | |
| lengths: [1] | |
| }; | |
| } | |
| // Recursively creates a tree that contains the given tree. | |
| function parentise(tree, h) | |
| { | |
| if (h === tree.height) | |
| { | |
| return tree; | |
| } | |
| return { | |
| ctor: '_Array', | |
| height: h, | |
| table: [parentise(tree, h - 1)], | |
| lengths: [length(tree)] | |
| }; | |
| } | |
| // Emphasizes blood brotherhood beneath two trees. | |
| function siblise(a, b) | |
| { | |
| return { | |
| ctor: '_Array', | |
| height: a.height + 1, | |
| table: [a, b], | |
| lengths: [length(a), length(a) + length(b)] | |
| }; | |
| } | |
| function toJSArray(a) | |
| { | |
| var jsArray = new Array(length(a)); | |
| toJSArray_(jsArray, 0, a); | |
| return jsArray; | |
| } | |
| function toJSArray_(jsArray, i, a) | |
| { | |
| for (var t = 0; t < a.table.length; t++) | |
| { | |
| if (a.height === 0) | |
| { | |
| jsArray[i + t] = a.table[t]; | |
| } | |
| else | |
| { | |
| var inc = t === 0 ? 0 : a.lengths[t - 1]; | |
| toJSArray_(jsArray, i + inc, a.table[t]); | |
| } | |
| } | |
| } | |
| function fromJSArray(jsArray) | |
| { | |
| if (jsArray.length === 0) | |
| { | |
| return empty; | |
| } | |
| var h = Math.floor(Math.log(jsArray.length) / Math.log(M)); | |
| return fromJSArray_(jsArray, h, 0, jsArray.length); | |
| } | |
| function fromJSArray_(jsArray, h, from, to) | |
| { | |
| if (h === 0) | |
| { | |
| return { | |
| ctor: '_Array', | |
| height: 0, | |
| table: jsArray.slice(from, to) | |
| }; | |
| } | |
| var step = Math.pow(M, h); | |
| var table = new Array(Math.ceil((to - from) / step)); | |
| var lengths = new Array(table.length); | |
| for (var i = 0; i < table.length; i++) | |
| { | |
| table[i] = fromJSArray_(jsArray, h - 1, from + (i * step), Math.min(from + ((i + 1) * step), to)); | |
| lengths[i] = length(table[i]) + (i > 0 ? lengths[i - 1] : 0); | |
| } | |
| return { | |
| ctor: '_Array', | |
| height: h, | |
| table: table, | |
| lengths: lengths | |
| }; | |
| } | |
| return { | |
| empty: empty, | |
| fromList: fromList, | |
| toList: toList, | |
| initialize: F2(initialize), | |
| append: F2(append), | |
| push: F2(push), | |
| slice: F3(slice), | |
| get: F2(get), | |
| set: F3(set), | |
| map: F2(map), | |
| indexedMap: F2(indexedMap), | |
| foldl: F3(foldl), | |
| foldr: F3(foldr), | |
| length: length, | |
| toJSArray: toJSArray, | |
| fromJSArray: fromJSArray | |
| }; | |
| }(); |