static void multiplyToRange(int currNode, int tSI, int tEI, int rSI, int rEI, long mulValue) { Node temp = tree[currNode]; /* System.out.println("MUL currNode : " + currNode + ", tSI : " + tSI + ", tEI : " + tEI + ", sum : " + temp.sum + ", mul : " + temp.mul); */ if (temp.mul > 1 || temp.add > 0) { temp.sum = temp.sum * temp.mul + temp.add; temp.sum %= mod; // System.out.println("mul done. sum : " + temp.sum); if (tSI != tEI) { tree[2 * currNode].mul *= temp.mul; tree[2 * currNode].mul %= mod; tree[2 * currNode].add *= temp.mul; tree[2 * currNode].add %= mod; tree[2 * currNode + 1].mul *= temp.mul; tree[2 * currNode + 1].mul %= mod; tree[2 * currNode + 1].add *= temp.mul; tree[2 * currNode + 1].add %= mod; } temp.mul = 1; temp.add = 0; } if (tSI > tEI || tSI > rEI || tEI < rSI) return; if (tSI >= rSI && tEI <= rEI) { temp.sum = temp.sum * mulValue + temp.add * mulValue; temp.sum %= mod; /* System.out.println("fully inside, sum : " + temp.sum + ", tSI : " + tSI + ", tEI : " + tEI);*/ if (tSI != tEI) { tree[2 * currNode].mul *= mulValue; tree[2 * currNode].mul %= mod; tree[2 * currNode + 1].mul *= mulValue; tree[2 * currNode + 1].mul %= mod; } temp.add = 0; // not needed // temp.mul = 1; return; } int mid = (tSI + tEI) / 2; multiplyToRange(2 * currNode, tSI, mid, rSI, rEI, mulValue); multiplyToRange(2 * currNode + 1, mid + 1, tEI, rSI, rEI, mulValue); temp.sum = tree[2 * currNode].sum + tree[2 * currNode + 1].sum; temp.sum %= mod; }

static long queryRangeSum(int currNode, int tSI, int tEI, int rSI, int rEI) { Node temp = tree[currNode]; /* System.out.println("Q-----currNode : " + currNode + ", tSI : " + tSI + ", tEI : " + tEI + ", tree[cN].sum : " + tree[currNode].sum);*/ if (temp.init != -1) { // System.out.println("currNode : " + currNode + ", in init"); temp.sum = ((tEI - tSI + 1) * temp.init); temp.sum %= mod; if (tSI != tEI) { tree[2 * currNode].init = temp.init; tree[2 * currNode + 1].init = temp.init; } temp.init = -1; temp.add = 0; temp.mul = 0; } else { temp.sum = (temp.sum * temp.mul) + ((tEI - tSI + 1) * temp.add); temp.sum %= mod; if (tSI != tEI) { tree[2 * currNode].add += temp.add; tree[2 * currNode].add %= mod; tree[2 * currNode].mul *= temp.mul; tree[2 * currNode].mul %= mod; tree[2 * currNode + 1].add += temp.add; tree[2 * currNode + 1].add %= mod; tree[2 * currNode + 1].mul *= temp.mul; tree[2 * currNode + 1].mul %= mod; } temp.add = 0; temp.mul = 1; } if (tSI > tEI || tSI > rEI || tEI < rSI) return -1; if (tSI >= rSI && tEI <= rEI) return temp.sum; int mid = (tSI + tEI) / 2; long lCS, rCS; lCS = queryRangeSum(2 * currNode, tSI, mid, rSI, rEI); rCS = queryRangeSum(2 * currNode + 1, mid + 1, tEI, rSI, rEI); if (lCS == -1) lCS = 0; if (rCS == -1) rCS = 0; tree[currNode].sum = tree[2 * currNode].sum + tree[2 * currNode + 1].sum; tree[currNode].sum %= mod; return (lCS + rCS) % mod; }

private Node testAndSplit(Node s, int k, int p, char c) { if (k > p) return s == sentinel ? null : s.get(c) == null ? s : null; Edge e = s.get(str.charAt(k)); if (c == str.charAt(e.a + p - k + 1)) return null; // check if char after implicit node is c Node r = new Node(); Edge re = new Edge(e.a + p - k + 1, e.b, e.end); r.add(re); Edge se = new Edge(e.a, e.a + p - k, r); s.add(se); return r; }

public void add(double[] point) { bounds.add(point); count++; if (splitter.test(point)) { if (null != left) { left.add(point); } } else { if (null != right) { right.add(point); } } }

@Test public void shouldSortCorrectlyWithManyElements() { node = new Node("Michelle"); node.add("Bill"); node.add("Jagruti"); node.add("Tess"); node.add("Sara"); node.add("Sue-Ellen"); node.add("Casey"); assertEquals( node.names(), Arrays.asList("Bill", "Casey", "Jagruti", "Michelle", "Sara", "Sue-Ellen", "Tess")); }

public void add(T value) { if (value.compareTo(data) < 0 && left == null) { left = new Node(); left.data = value; } else if (value.compareTo(data) > 0 && right == null) { right = new Node(); right.data = value; } else if (value.compareTo(data) < 0 && left != null) { left.add(value); } else if (value.compareTo(data) > 0 && right != null) { right.add(value); } // dont't do anything if the value is equal to data }

public void add(T value) { if (value.compareTo(data) < 0) { if (left == null) { left = new Node(value); } else { left.add(value); } } else { if (right == null) { right = new Node(value); } else { right.add(value); } } }

public void add(T value) { if (root == null) { root = new Node(value); } else { root.add(value); } }

@Test( dataProvider = "singleNode", dataProviderClass = NodeProvider.class, dependsOnGroups = {"arithmetic"}) public void equalityTest(Node n) { assert n.equals(n); assert n.equals(new Node(n.getX(), n.getY())); assert !n.equals(n.add(new Node(1., 1.))); assert !n.equals(n.subtract(new Node(1., 1.))); // test strictness Node tinyDiff = new Node(Rounding.EQUALITY_DIFFERENCE / 2., Rounding.EQUALITY_DIFFERENCE / 2.); assert !n.equals(n.add(tinyDiff)); assert !n.equals(n.subtract(tinyDiff)); assert n.equals(n.add(tinyDiff), false); assert n.equals(n.subtract(tinyDiff), false); }

@Test( dataProvider = "doubleNodes", dataProviderClass = NodeProvider.class, groups = {"arithmetic"}) public void additionTest(Node a, Node b) { Node added = a.add(b); assert Rounding.isEqual(added.getX(), a.getX() + b.getX()); assert Rounding.isEqual(added.getY(), a.getY() + b.getY()); }

private void addFamilies() { for (Object[] element : initialData) { Object[] data = new Object[] {element[0], null, element[2]}; FamilyNode child = new FamilyNode(data); root.add(child); PersonNode person = new PersonNode(element); child.add(person); addNames(person); addPeople(child); } }

private void add(String[] words, int iWord, T value) { if (iWord >= words.length) { fValue = value; return; } Node kid = fKids.get(words[iWord]); if (kid == null) { fKids.put(words[iWord], kid = new Node()); } kid.add(words, iWord + 1, value); }

static void addToRange( int currNode, int tSI, int tEI, int rSI, int rEI, long addValue) // fine, I guess { Node temp = tree[currNode]; if (temp.add > 0 || temp.mul > 1) { temp.sum = (temp.sum * temp.mul) + ((tEI - tSI + 1) * temp.add); temp.sum %= mod; if (tSI != tEI) { tree[2 * currNode].add += temp.add; tree[2 * currNode].add %= mod; tree[2 * currNode].mul *= temp.mul; tree[2 * currNode].mul %= mod; tree[2 * currNode + 1].add += temp.add; tree[2 * currNode + 1].add %= mod; tree[2 * currNode + 1].mul *= temp.mul; tree[2 * currNode + 1].mul %= mod; } temp.add = 0; temp.mul = 1; } if (tSI > tEI || tSI > rEI || tEI < rSI) return; if (tSI >= rSI && tEI <= rEI) { temp.sum = temp.sum * temp.mul + ((tEI - tSI + 1) * addValue); temp.sum %= mod; if (tSI != tEI) { tree[2 * currNode].add += addValue; tree[2 * currNode].add %= mod; tree[2 * currNode].mul *= temp.mul; tree[2 * currNode].mul %= mod; tree[2 * currNode + 1].add += addValue; tree[2 * currNode + 1].add %= mod; tree[2 * currNode + 1].mul *= temp.mul; tree[2 * currNode + 1].mul %= mod; } temp.mul = 1; return; } int mid = (tSI + tEI) / 2; addToRange(2 * currNode, tSI, mid, rSI, rEI, addValue); addToRange(2 * currNode + 1, mid + 1, tEI, rSI, rEI, addValue); temp.sum = tree[2 * currNode].sum + tree[2 * currNode + 1].sum; temp.sum %= mod; }

private Node update(Node s, int[] k, int i) { Node oldr = root, r = testAndSplit(s, k[0], i - 1, str.charAt(i)); while (r != null) { Node rp = new Node(); Edge e = new Edge(i, INF, rp); r.add(e); if (oldr != root) oldr.suffix = r; oldr = r; s = canonize(s.suffix, k, i - 1); r = testAndSplit(s, k[0], i - 1, str.charAt(i)); } if (oldr != root) oldr.suffix = s; return s; }

/** * Initialise a node * * @param node the node * @param key the key */ public boolean init(Node node, Object key) { if (!(key instanceof short[])) { return false; } short[] data = (short[]) key; node.setHeader(HEADER_DATA_ARRAY); node.addPointer(getCreator().getType("[S")); node.addData(data.length); for (int i = 0, n = data.length; i < n; i += 2) { int value = get(i, data) << 16 | get(i + 1, data); node.add(new ShortSlot(value)); } return true; }

public void add(String[] words, T value) { fRoot.add(words, 0, value); }

static void initializeRange(int currNode, int tSI, int tEI, int rSI, int rEI, long initValue) { Node temp = tree[currNode]; if (temp.init != -1) { temp.sum = ((tEI - tSI + 1) * temp.init); temp.sum %= mod; if (tSI != tEI) { tree[2 * currNode].init = temp.init; tree[2 * currNode + 1].init = temp.init; } temp.init = -1; temp.add = 0; temp.mul = 1; } else if (temp.add > 0 || temp.mul > 1) { temp.sum = temp.sum * temp.mul + ((tEI - tSI + 1) * temp.add); temp.sum %= mod; if (tSI != tEI) { tree[2 * currNode].add += temp.add; tree[2 * currNode].add %= mod; tree[2 * currNode + 1].add += temp.add; tree[2 * currNode + 1].add %= mod; tree[2 * currNode].mul *= temp.mul; tree[2 * currNode].mul %= mod; tree[2 * currNode + 1].mul *= temp.mul; tree[2 * currNode + 1].mul %= mod; } temp.init = -1; temp.add = 0; temp.mul = 1; } /* System.out.println("INIT cN : " + currNode + ", tSI : " + tSI + ", tEI : " + tEI + ", rSI : " + rSI + ", rEI : " + rEI);*/ if (tSI > tEI || tSI > rEI || tEI < rSI) return; if (tSI >= rSI && tEI <= rEI) { temp.sum = (tEI - tSI + 1) * initValue; temp.sum %= mod; if (tSI != tEI) { tree[2 * currNode].init = initValue; tree[2 * currNode + 1].init = initValue; } temp.add = 0; temp.mul = 1; return; } int mid = (tSI + tEI) / 2; initializeRange(2 * currNode, tSI, mid, rSI, rEI, initValue); initializeRange(2 * currNode + 1, mid + 1, tEI, rSI, rEI, initValue); tree[currNode].sum = tree[2 * currNode].sum + tree[2 * currNode + 1].sum; tree[currNode].sum %= mod; }

public void insert(String s, int index) { // change the current index of remaining suffixes // System.out.println(s+" being added in the tree------------------------"); // System.out.println(" index= "+index); suffix ob = new suffix(index); suffix.setCurrent(index); suffixes.add(ob); // change the current index of all leafedges // updateLeafEdges(index); LeafEdge.setCurrent(index); // insert the given suffix at the active point while (suffixes.isEmpty() == false) { Node activeNode = act_point.getNode(); Edge activeEdge = act_point.getEdge(); int act_len = act_point.getActiveLength(); // System.out.println("Active POINT is:::::::"); // System.out.println("active node is "+activeNode.label); // if(activeEdge==null) // System.out.println("active Edge is null "); // else // System.out.println("active Edge is "+activeEdge.label); // System.out.println("active length is "+act_len); // search at the active node for the given word that is to be inserted Edge EdgeOfWord = activeNode.search(s, index); if (activeEdge == null) { if (EdgeOfWord == null) { // insertion at the root.jst directly add the edge with the given string in the tree at // the root; // this edge will be a leaf edge Node dest = new Node(s); dest.label = "Node" + Nid; Nid++; LeafEdge ed = new LeafEdge(index, index, activeNode, dest); ed.label = "Edge" + Eid; Eid++; // this edge will be added to the set of leafedges leafEdges.add(ed); // add this edge to the map of edges in active node activeNode.add(s, ed); // remove the suffix inserted // change the current of suffixes // suffixes.remove(); // System.out.println(s+" added in tree"); suffix ob1 = suffixes.remove(); // printLeafEdges(); } else { // given word is present at the active node // update the active point // active node remains same // active edge is changed // active length is incremented // remainder is incremented act_point.setActiveEdge(EdgeOfWord); act_point.incActiveLength(); remainder++; checkWhetherActEdgeEndsOnNode(); // System.out.println(s+" already presnt in tree"); // System.out.println("activeLength is "+act_point.activeLength); // printLeafEdges(); break; } } else { // check whether active edge contains the word to be inserted // retrieve the word present at the active length in the active edge int pos = activeEdge.getTrueIndex(act_len); // System.out.println("check whether active edge contains the "+ s +" to be inserted"); // System.out.println("comparing "+s +"and positon "+pos +" in array doc"); if (s.equalsIgnoreCase(doc[pos])) { act_point.incActiveLength(); // System.out.println(" active edge contains "+ s +" to be inserted"); // System.out.println("activeLength is "+act_point.activeLength); remainder++; checkWhetherActEdgeEndsOnNode(); // printLeafEdges(); break; } else { // split the activeedge and create one new edge // set the end of active edge // System.out.println("at active node "+activeNode.label); // System.out.println("splitting activeEdge which stats with"+ // doc[(act_point.getEdge()).getStartIndex()]); activeEdge.setEnd(index); // System.out.println("set end of activeEdge to // "+doc[(act_point.getEdge()).getEndIndex()]); Node n1 = new Node(); n1.label = "Node" + Nid; Nid++; Node n2 = new Node(); n2.label = "Node" + Nid; Nid++; Node source = activeEdge.getDestNode(); int start = activeEdge.getStartIndex(); int end = activeEdge.getEndIndex(); // create 2 new leaf edges LeafEdge e1 = new LeafEdge(start + act_len, end, source, n1); e1.label = "Edge" + Eid; Eid++; LeafEdge e2 = new LeafEdge(end, end, source, n2); e2.label = "Edge" + Eid; Eid++; // System.out.println("create one new edge stating with "+doc[e1.getStartIndex()]+" and // ending with "+doc[e1.getEndIndex()]); // System.out.println("create second new edge stating with "+doc[e2.getStartIndex()]+" // and ending with "+doc[e2.getEndIndex()]); // add these leafedges to their respective nodes source.add(doc[start + act_len], e1); source.add(s, e2); // update end of active edge activeEdge.setEnd(start + act_len - 1); // System.out.println("set end of activeEdge to // "+doc[(act_point.getEdge()).getEndIndex()]); // remove active edge fom the set of leafedges leafEdges.remove(activeEdge); // add above 2 newly created leaf edges into the set of leafedges leafEdges.add(e1); leafEdges.add(e2); remainder--; addLink(source); suffix ob1 = suffixes.remove(); changeActivePoint(); // System.out.println("activeLength is "+act_point.activeLength); // printLeafEdges(); } } } if (suffixes.isEmpty() == true) { suffix.setCurrent(-1); link = null; } // printSuffixes(); }

@Test public void shouldSortCorrectlyWithThreeElements() { node.add("Aaron"); node.add("Emily"); assertEquals(node.names(), Arrays.asList("Aaron", "Emily", "Walker")); }

Node parse_(byte[] expression) { Node result = null; Node expr = null; int wholeTermStart = index; int subtermStart = index; boolean subtermComplete = false; while (index < expression.length) { switch (expression[index++]) { case '&': { expr = processTerm(subtermStart, index - 1, expr, expression); if (result != null) { if (!result.type.equals(NodeType.AND)) throw new BadArgumentException( "cannot mix & and |", new String(expression, UTF_8), index - 1); } else { result = new Node(NodeType.AND, wholeTermStart); } result.add(expr); expr = null; subtermStart = index; subtermComplete = false; break; } case '|': { expr = processTerm(subtermStart, index - 1, expr, expression); if (result != null) { if (!result.type.equals(NodeType.OR)) throw new BadArgumentException( "cannot mix | and &", new String(expression, UTF_8), index - 1); } else { result = new Node(NodeType.OR, wholeTermStart); } result.add(expr); expr = null; subtermStart = index; subtermComplete = false; break; } case '(': { parens++; if (subtermStart != index - 1 || expr != null) throw new BadArgumentException( "expression needs & or |", new String(expression, UTF_8), index - 1); expr = parse_(expression); subtermStart = index; subtermComplete = false; break; } case ')': { parens--; Node child = processTerm(subtermStart, index - 1, expr, expression); if (child == null && result == null) throw new BadArgumentException( "empty expression not allowed", new String(expression, UTF_8), index); if (result == null) return child; if (result.type == child.type) for (Node c : child.children) result.add(c); else result.add(child); result.end = index - 1; return result; } case '"': { if (subtermStart != index - 1) throw new BadArgumentException( "expression needs & or |", new String(expression, UTF_8), index - 1); while (index < expression.length && expression[index] != '"') { if (expression[index] == '\\') { index++; if (expression[index] != '\\' && expression[index] != '"') throw new BadArgumentException( "invalid escaping within quotes", new String(expression, UTF_8), index - 1); } index++; } if (index == expression.length) throw new BadArgumentException( "unclosed quote", new String(expression, UTF_8), subtermStart); if (subtermStart + 1 == index) throw new BadArgumentException( "empty term", new String(expression, UTF_8), subtermStart); index++; subtermComplete = true; break; } default: { if (subtermComplete) throw new BadArgumentException( "expression needs & or |", new String(expression, UTF_8), index - 1); byte c = expression[index - 1]; if (!Authorizations.isValidAuthChar(c)) throw new BadArgumentException( "bad character (" + c + ")", new String(expression, UTF_8), index - 1); } } } Node child = processTerm(subtermStart, index, expr, expression); if (result != null) { result.add(child); result.end = index; } else result = child; if (result.type != NodeType.TERM) if (result.children.size() < 2) throw new BadArgumentException("missing term", new String(expression, UTF_8), index); return result; }

public void add(double[] point) { assert (dimensions == point.length); root.add(point); }