protected void ApplyArrayRank <T> (RCArray <T> inputData, RCArray <int> inputIndex, Dictionary <long, int> map, int axisCount, out RCArray <T> data, out RCArray <int> index) { RCArray <long> im = new RCArray <long> (inputData.Count); T[] fd = new T[inputData.Count]; int[] fi = new int[inputData.Count]; if (inputIndex != null) { // Any rows that are lacking values in the sort column will be missing from map. // Push these rows so that they come after all the rows with valid values in the // sort // column. // But importantly, they are kept in the original order. for (int j = 0; j < inputIndex.Count; ++j) { int newRow; if (!map.TryGetValue(inputIndex[j], out newRow)) { throw new Exception(string.Format("inputIndex[j]: {0} was not represented in map!", inputIndex[j])); } im.Write(newRow); } } else { for (int j = 0; j < inputData.Count; ++j) { int newRow; if (!map.TryGetValue(j, out newRow)) { newRow = map.Count + j; } im.Write(newRow); } } // Now rank the values in im ascending. long[] rim = RankUtils.DoRank <long> (SortDirection.asc, 'l', im); for (int j = 0; j < rim.Length; ++j) { fd[j] = inputData[(int)rim[j]]; fi[j] = (int)im[(int)rim[j]]; } index = new RCArray <int> (fi); data = new RCArray <T> (fd); }
protected RCCube SortCubeByDirectionAndColumn(RCSymbol left, RCCube right) { if (right.Count == 0) { return(right); } SortDirection direction = Sort.ToDir(left); string name = (string)left[0].Part(1); ColumnBase sortCol = right.GetColumn(name); RCArray <ColumnBase> columns = new RCArray <ColumnBase> ((int)right.Cols); long[] rank; if (sortCol == null) { switch (name) { case "G": rank = RankUtils.DoRank <long> (direction, 'l', right.Axis.Global); break; case "E": rank = RankUtils.DoRank <long> (direction, 'l', right.Axis.Event); break; case "T": rank = RankUtils.DoRank <RCTimeScalar> (direction, 't', right.Axis.Time); break; case "S": rank = RankUtils.DoRank <RCSymbolScalar> (direction, 's', right.Axis.Symbol); break; default: throw new Exception("Unknown timeline column: " + name); } } else { switch (sortCol.TypeCode) { case 'x': rank = RankUtils.DoRank <byte> (direction, sortCol.TypeCode, (RCArray <byte>)sortCol.Array); break; case 'l': rank = RankUtils.DoRank <long> (direction, sortCol.TypeCode, (RCArray <long>)sortCol.Array); break; case 'd': rank = RankUtils.DoRank <double> (direction, sortCol.TypeCode, (RCArray <double>)sortCol.Array); break; case 'm': rank = RankUtils.DoRank <decimal> (direction, sortCol.TypeCode, (RCArray <decimal>)sortCol.Array); break; case 's': rank = RankUtils.DoRank <string> (direction, sortCol.TypeCode, (RCArray <string>)sortCol.Array); break; case 'b': rank = RankUtils.DoRank <bool> (direction, sortCol.TypeCode, (RCArray <bool>)sortCol.Array); break; case 'y': rank = RankUtils.DoRank <RCSymbolScalar> (direction, sortCol.TypeCode, (RCArray <RCSymbolScalar>)sortCol.Array); break; case 't': rank = RankUtils.DoRank <RCTimeScalar> (direction, sortCol.TypeCode, (RCArray <RCTimeScalar>)sortCol.Array); break; default: throw new Exception("Type:" + sortCol.TypeCode + " is not supported by sort"); } } int[] rowRank = new int[rank.Length]; if (sortCol == null) { for (int i = 0; i < rowRank.Length; ++i) { rowRank[i] = (int)rank[i]; } } else { for (int i = 0; i < rowRank.Length; ++i) { rowRank[i] = sortCol.Index[(int)rank[i]]; } } Dictionary <long, int> map = new Dictionary <long, int> (); for (int i = 0; i < rowRank.Length; ++i) { map[rowRank[i]] = i; } Timeline axis = ApplyAxisRank(right.Axis, map); int lastRow = map.Count; for (int i = 0; i < axis.Count; ++i) { if (!map.ContainsKey(i)) { map[i] = lastRow; ++lastRow; } } for (int col = 0; col < right.Cols; ++col) { ColumnBase oldcol = right.GetColumn(col); ColumnBase newcol = null; switch (oldcol.TypeCode) { case 'x': newcol = DoColumn <byte> (oldcol, map, axis); break; case 'l': newcol = DoColumn <long> (oldcol, map, axis); break; case 'd': newcol = DoColumn <double> (oldcol, map, axis); break; case 'm': newcol = DoColumn <decimal> (oldcol, map, axis); break; case 's': newcol = DoColumn <string> (oldcol, map, axis); break; case 'b': newcol = DoColumn <bool> (oldcol, map, axis); break; case 'y': newcol = DoColumn <RCSymbolScalar> (oldcol, map, axis); break; case 't': newcol = DoColumn <RCTimeScalar> (oldcol, map, axis); break; case '0': newcol = oldcol; break; default: throw new Exception("Type:" + newcol.TypeCode + " is not supported by sort"); } columns.Write(newcol); } RCArray <string> names = new RCArray <string> (columns.Count); for (int i = 0; i < right.Cols; ++i) { names.Write(right.NameAt(i)); } RCCube result = new RCCube(axis, names, columns); return(result); }
public void EvalSort(RCRunner runner, RCClosure closure, RCSymbol left, RCBlock right) { SortDirection direction = ToDir(left); string col = (string)left[0].Part(1); RCVectorBase column = (RCVectorBase)right.Get(col); // It would be nice if there was an easy way to call one operator from another. // I tried to add one but found I would have to create a weird closure for this // purpose. // So I decided to wait and see and live with the switch statement for now. RCLong rank; switch (column.TypeCode) { case 'x': rank = new RCLong(RankUtils.DoRank <byte> (direction, (RCByte)column)); break; case 'l': rank = new RCLong(RankUtils.DoRank <long> (direction, (RCLong)column)); break; case 'd': rank = new RCLong(RankUtils.DoRank <double> (direction, (RCDouble)column)); break; case 'm': rank = new RCLong(RankUtils.DoRank <decimal> (direction, (RCDecimal)column)); break; case 's': rank = new RCLong(RankUtils.DoRank <string> (direction, (RCString)column)); break; case 'b': rank = new RCLong(RankUtils.DoRank <bool> (direction, (RCBoolean)column)); break; case 'y': rank = new RCLong(RankUtils.DoRank <RCSymbolScalar> (direction, (RCSymbol)column)); break; case 't': rank = new RCLong(RankUtils.DoRank <RCTimeScalar> (direction, (RCTime)column)); break; default: throw new Exception("Type:" + column.TypeCode + " is not supported by sort"); } RCBlock result = RCBlock.Empty; for (int i = 0; i < right.Count; ++i) { RCBlock name = right.GetName(i); column = (RCVectorBase)name.Value; RCValue reordered; switch (column.TypeCode) { case 'x': reordered = ReorderColumn <byte> (rank, (RCVector <byte>)column); break; case 'l': reordered = ReorderColumn <long> (rank, (RCVector <long>)column); break; case 'd': reordered = ReorderColumn <double> (rank, (RCVector <double>)column); break; case 'm': reordered = ReorderColumn <decimal> (rank, (RCVector <decimal>)column); break; case 's': reordered = ReorderColumn <string> (rank, (RCVector <string>)column); break; case 'b': reordered = ReorderColumn <bool> (rank, (RCVector <bool>)column); break; case 'y': reordered = ReorderColumn <RCSymbolScalar> (rank, (RCVector <RCSymbolScalar>)column); break; case 't': reordered = ReorderColumn <RCTimeScalar> (rank, (RCVector <RCTimeScalar>)column); break; default: throw new Exception("Type:" + column.TypeCode + " is not supported by sort"); } result = new RCBlock(result, name.Name, ":", reordered); } runner.Yield(closure, result); }
public void EvalRank(RCRunner runner, RCClosure closure, RCByte right) { runner.Yield(closure, new RCLong(RankUtils.DoRank <byte> (SortDirection.asc, right))); }
public void EvalRank(RCRunner runner, RCClosure closure, RCSymbol left, RCTime right) { runner.Yield(closure, new RCLong(RankUtils.DoRank <RCTimeScalar> (Sort.ToDir(left), right))); }
public void EvalRank(RCRunner runner, RCClosure closure, RCSymbol left, RCBoolean right) { runner.Yield(closure, new RCLong(RankUtils.DoRank <bool> (Sort.ToDir(left), right))); }