コード例 #1
0
        public void Test3()
        {
            var cfg = GenerateCFG(
                @"{
a = 5;
1:
b = c;
2:
goto 2;
goto 1;
d = a;
goto 1;
}");

            /*
             *  5 блоков
             *  0 {a = 5}
             *  1 {1: b = c}
             *  2 {2: goto 2}
             *  3 {goto 1}
             *  4 {d = a; goto 1}
             */
            var dict = cfg.classifyEdges();

            Assert.AreEqual(dict[IndexEdge.Create(2, 2)], EdgeType.Retreating);
            Assert.AreEqual(dict[IndexEdge.Create(4, 6)], EdgeType.Cross);
            Assert.AreEqual(dict[IndexEdge.Create(3, 1)], EdgeType.Cross);
            dict.Remove(IndexEdge.Create(2, 2));
            dict.Remove(IndexEdge.Create(4, 6));
            dict.Remove(IndexEdge.Create(3, 1));
            Assert.False(dict.Values.Any(type => type != EdgeType.Advancing));
            BasicBlock.clearIndexCounter();
        }
コード例 #2
0
        public IEnumerable <IndexEdge <TEntity> > ToEdgeResults()
        {
            //The Linq Selection provides IEnumerable for us...
            //Note: that's why we do NOT call ToList() here so that consuming classes may provide additional filtering...
            var results = this.CursorPage?.CursorResults
                          .Where(cr => cr != null)
                          .Select(cr => IndexEdge <TEntity> .Create(cr.Entity, cr.CursorIndex));

            return(results);
        }
コード例 #3
0
    private static CursorPagingRange SliceRange(
        CursorPagingArguments arguments,
        int maxElementCount)
    {
        // [SPEC] if after is set then remove all elements of edges before and including
        // afterEdge.
        //
        // The cursor is increased by one so that the index points to the element after
        var startIndex = arguments.After is { } a
            ? IndexEdge <TEntity> .DeserializeCursor(a) + 1
            : 0;

        // [SPEC] if before is set then remove all elements of edges before and including
        // beforeEdge.
        var before = arguments.Before is { } b
            ? IndexEdge <TEntity> .DeserializeCursor(b)
            : maxElementCount;

        // if after is negative we have know how much of the offset was in the negative range.
        // The amount of positions that are in the negative range, have to be subtracted from
        // the take or we will fetch too many items.
        var startOffsetCorrection = 0;

        if (startIndex < 0)
        {
            startOffsetCorrection = Math.Abs(startIndex);
            startIndex            = 0;
        }

        CursorPagingRange range = new(startIndex, before);

        //[SPEC] If first is less than 0 throw an error
        ValidateFirst(arguments, out var first);

        if (first is not null)
        {
            first -= startOffsetCorrection;
            if (first < 0)
            {
                first = 0;
            }
        }

        //[SPEC] Slice edges to be of length first by removing edges from the end of edges.
        range.Take(first);

        //[SPEC] if last is less than 0 throw an error
        ValidateLast(arguments, out var last);

        //[SPEC] Slice edges to be of length last by removing edges from the start of edges.
        range.TakeLast(last);

        return(range);
    }
コード例 #4
0
        public void Test2()
        {
            var cfg = GenerateCFG(
                @"{
goto 1;
a = 5;
1:
while (a == 5)
{
x = 7;
}
if (z > 99)
{
f = 5;
}
else
{
b = 1;
}
a = 5 == 2;
}");

            /*
             *  10 блоков
             *  0 {goto 1}
             *  1 {a = 5}
             *  2 {1}
             *  3 {#L0 #t0 = a == 5; if #t0 goto #L1}
             *  4 {goto #L2}
             *  5 {#L1 x = 7; goto #L0}
             *  6 {#L2 #t1 = z > 99; if #t1 goto #L3}
             *  7 {b = 1; goto #L4}
             *  8 {#L3 f = 5}
             *  9 {#L4 #t2 = 5 == 2; a = #t2}
             */
            var dict = cfg.classifyEdges();

            Assert.AreEqual(dict[IndexEdge.Create(1, 2)], EdgeType.Cross);
            Assert.AreEqual(dict[IndexEdge.Create(5, 3)], EdgeType.Retreating);
            dict.Remove(IndexEdge.Create(1, 2));
            dict.Remove(IndexEdge.Create(5, 3));
            Assert.False(dict.Values.Any(type => type != EdgeType.Advancing));
            BasicBlock.clearIndexCounter();
        }
コード例 #5
0
        protected override ValueTask <Connection> SliceAsync(IResolverContext context, object source, CursorPagingArguments arguments)
        {
            //If Appropriate we handle the values here to ensure that no post-processing is done other than
            //  correctly mapping the results into a GraphQL Connection as Edges with Cursors...
            if (source is IPreProcessedCursorSlice <TEntity> pagedResults)
            {
                bool includeTotalCountEnabled = this.PagingOptions.IncludeTotalCount ?? PagingDefaults.IncludeTotalCount;
                var  graphQLParamsContext     = new GraphQLParamsContext(context);

                //Optimized to only require TotalCount value if the query actually requested it!
                if (includeTotalCountEnabled && graphQLParamsContext.IsTotalCountRequested && pagedResults.TotalCount == null)
                {
                    throw new InvalidOperationException($"Total Count is requested in the query, but was not provided with the results [{this.GetType().GetTypeName()}] from the resolvers pre-processing logic; TotalCount is null.");
                }

                int?totalCount = pagedResults.TotalCount;

                //Ensure we are null safe and return a valid empty list by default.
                IReadOnlyList <IndexEdge <TEntity> > selectedEdges =
                    pagedResults?.ToEdgeResults().ToList() ?? new List <IndexEdge <TEntity> >();;

                IndexEdge <TEntity>?firstEdge = selectedEdges.FirstOrDefault();
                IndexEdge <TEntity>?lastEdge  = selectedEdges.LastOrDefault();

                var connectionPageInfo = new ConnectionPageInfo(
                    hasNextPage: pagedResults?.HasNextPage ?? false,
                    hasPreviousPage: pagedResults?.HasPreviousPage ?? false,
                    startCursor: firstEdge?.Cursor,
                    endCursor: lastEdge?.Cursor,
                    totalCount: totalCount ?? 0
                    );

                var graphQLConnection = new Connection <TEntity>(
                    selectedEdges,
                    connectionPageInfo,
                    ct => new ValueTask <int>(connectionPageInfo.TotalCount ?? 0)
                    );

                return(new ValueTask <Connection>(graphQLConnection));
            }

            throw new GraphQLException($"[{nameof(PreProcessedCursorPagingHandler<TEntity>)}] cannot handle the specified data source of type [{source.GetType().Name}].");
        }
コード例 #6
0
        public async ValueTask <IReadOnlyList <Edge <TEntity> > > ExecuteQueryAsync(
            int offset,
            CancellationToken cancellationToken)
        {
            var list = new List <IndexEdge <TEntity> >();

            using IAsyncCursor <TEntity> cursor = await _source
                                                  .ToCursorAsync(cancellationToken)
                                                  .ConfigureAwait(false);

            var index = offset;

            while (await cursor.MoveNextAsync(cancellationToken).ConfigureAwait(false))
            {
                foreach (TEntity item in cursor.Current)
                {
                    list.Add(IndexEdge <TEntity> .Create(item, index++));
                }
            }

            return(list);
        }
コード例 #7
0
ファイル: Delaunay.cs プロジェクト: abordt/Viking
        /// <summary>
        /// Generates the delaunay triangulation for a list of points. 
        /// Requires the points to be sorted on the X-axis coordinate!
        /// Every the integers in the returned array are the indicies in the passes array of triangles. 
        /// Implemented based upon: http://local.wasp.uwa.edu.au/~pbourke/papers/triangulate/
        /// "Triangulate: Efficient Triangulation Algorithm Suitable for Terrain Modelling"
        /// by Paul Bourke
        /// </summary>
        public static int[] Triangulate(GridVector2[] points, GridVector2[] BoundingPoints)
        {
            if (BoundingPoints == null)
            {
                throw new ArgumentNullException("BoundingPoints");
            }

            if (points == null)
            {
                throw new ArgumentNullException("points");
            }

            if (points.Length < 3)
                return new int[0];

            #if DEBUG

            //Check to ensure the input is really sorted on the X-Axis
            for (int iDebug = 1; iDebug < points.Length; iDebug++)
            {
                Debug.Assert(points[iDebug - 1].X <= points[iDebug].X);
                Debug.Assert(GridVector2.Distance(points[iDebug - 1], points[iDebug]) >= Global.Epsilon);
            }

            #endif

            List<GridIndexTriangle> triangles = new List<GridIndexTriangle>(points.Length);

            //Safe triangles have a circle with a center.X+radius which is less than the current point.
            //This means they can never intersect with a new point and we never need to test them again.
            List<GridIndexTriangle> safeTriangles = new List<GridIndexTriangle>();

            int iNumPoints = points.Length;
            GridVector2[] allpoints = new GridVector2[iNumPoints + 4];

            points.CopyTo(allpoints, 0);
            BoundingPoints.CopyTo(allpoints, iNumPoints);

            //Initialize bounding triangles
            triangles.AddRange(new GridIndexTriangle[] { new GridIndexTriangle(iNumPoints, iNumPoints + 1, iNumPoints + 2, ref allpoints),
                                                         new GridIndexTriangle(iNumPoints + 1, iNumPoints + 2, iNumPoints + 3, ref allpoints) });

            IndexEdge[] Edges = new IndexEdge[(triangles.Count * 3) * 2];
            for(int iPoint = 0; iPoint < points.Length; iPoint++)
            {
                GridVector2 P = points[iPoint];

                //Use preallocated buffer if we can, otherwise expand it
                int maxEdges = triangles.Count * 3;
                if (Edges.Length < maxEdges)
                    Edges = new IndexEdge[maxEdges * 2];

                int iTri = 0;
                int iEdge = 0;
                while(iTri < triangles.Count)
                {
                    GridIndexTriangle tri = triangles[iTri];
                    GridCircle circle = tri.Circle;
                    if (circle.Contains(P))
                    {
                        Edges[iEdge++] = new IndexEdge(tri.i1, tri.i2);
                        Edges[iEdge++] = new IndexEdge(tri.i2, tri.i3);
                        Edges[iEdge++] = new IndexEdge(tri.i3, tri.i1);

            /*                        Edges.AddRange(new IndexEdge[] {new IndexEdge(tri.i1, tri.i2),
                                                               new IndexEdge(tri.i2, tri.i3),
                                                               new IndexEdge(tri.i3, tri.i1)});
                        */
                        triangles.RemoveAt(iTri);
                    }
                    //Check if the triangle is safe from ever intersecting with a new point again
                    else if (circle.Center.X + circle.Radius + Global.Epsilon < P.X)
                    {
                        safeTriangles.Add(tri);
                        triangles.RemoveAt(iTri);
                    }
                    else
                    {
                        iTri++;
                    }
                }

                //Record how many edges there are
                int numEdges = iEdge;

                //Remove duplicates from edge buffer
                //This is easier with a list, but arrays were faster
                for (int iA = 0; iA < numEdges; iA++)
                {
                    if (Edges[iA].IsValid == false)
                        continue;

                    for (int iB = iA + 1; iB < numEdges; iB++)
                    {
                        if (Edges[iB].IsValid == false)
                            continue;

                        if (Edges[iA] == Edges[iB])
                        {
                            Edges[iB].IsValid = false;
                            Edges[iA].IsValid = false;
                            break;
                        }
                    }
                }

                //Add triangles with the remaining edges
                for(iEdge = 0; iEdge < numEdges; iEdge++)
                {
                    IndexEdge E = Edges[iEdge];

                    if (!E.IsValid)
                        continue;

                    GridIndexTriangle newTri = new GridIndexTriangle(E.iA, E.iB, iPoint, ref allpoints);
                    triangles.Add(newTri);

            #if DEBUG
                    //Check to make sure the new triangle intersects the point.  This is a slow test.
                    Debug.Assert(((GridTriangle)newTri).Intersects(P));
            #endif
                }
            }

            //Return all the safe triangles to the triangles list
            triangles.AddRange(safeTriangles);

            //Yank all the triangles that are part of the bounding triangles
            for (int iTri = 0; iTri < triangles.Count; iTri++)
            {
                GridIndexTriangle tri = triangles[iTri];
                if (tri.i1 >= iNumPoints ||
                   tri.i2 >= iNumPoints ||
                   tri.i3 >= iNumPoints)
                {
                    triangles.RemoveAt(iTri);
                    iTri--;
                }
            }

            //Build a list of triangle indicies to return
            int[] TriangleIndicies = new int[triangles.Count * 3];
            for (int iTri = 0; iTri < triangles.Count; iTri++)
            {
                GridIndexTriangle tri = triangles[iTri];
                int iPoint = iTri * 3;
                TriangleIndicies[iPoint] = tri.i1;
                TriangleIndicies[iPoint + 1] = tri.i2;
                TriangleIndicies[iPoint + 2] = tri.i3;
            }

            return TriangleIndicies;
        }
        public static ICursorPageSlice <T> SliceAsCursorPage <T>(this IEnumerable <T> items, string?after, int?first, string?before, int?last)
            where T : class
        {
            //Do nothing if there are no results...
            if (!items.Any())
            {
                return(new CursorPageSlice <T>(Enumerable.Empty <ICursorResult <T> >(), 0, false, false));
            }

            var afterIndex = after != null
                ? IndexEdge <string> .DeserializeCursor(after)
                : 0;

            var beforeIndex = before != null
                ? IndexEdge <string> .DeserializeCursor(before)
                : 0;

            //FIRST log the index of all items in the list BEFORE slicing, as these indexes are
            //  the Cursor Indexes for paging up/down the entire list, & ICursorResult is the Decorator
            //  around the Entity Models.

            //NOTE: We MUST materialize this after applying index values to prevent ongoing increments...
            int index = 0;
            IEnumerable <ICursorResult <T> > slice = items
                                                     .Select(c => new CursorResult <T>(c, ++index))
                                                     .ToList();

            int totalCount = slice.Count();

            //If After specified, remove all before After (or skip past After)
            if (afterIndex > 0 && slice.Last().CursorIndex > afterIndex)
            {
                slice = slice.Skip(afterIndex);
            }

            //If Before is specified, remove all after Before (Skip Until Before is reached)
            if (beforeIndex > 0 && slice.Last().CursorIndex > beforeIndex)
            {
                slice = slice.SkipWhile(c => c.CursorIndex < beforeIndex);
            }

            //If First is specified, then take the first/top rows from the current Slice!
            if (first.HasValue && first > 0 && slice.Count() > first)
            {
                slice = slice.Take(first.Value);
            }

            //If First is specified, then take the first/top rows from the current Slice!
            if (last.HasValue && last > 0 && slice.Count() > last)
            {
                slice = slice.TakeLast(last.Value);
            }

            //Wrap all results into a PagedCursor Slice result wit Total Count...
            //NOTE: to ensure our pagination is complete, we materialize the Results!
            var results     = slice.ToList();
            var firstCursor = results.FirstOrDefault();
            var lastCursor  = results.LastOrDefault();

            var cursorPageSlice = new CursorPageSlice <T>(
                results,
                totalCount,
                hasPreviousPage: firstCursor?.CursorIndex > 1,
                hasNextPage: lastCursor?.CursorIndex < totalCount
                );

            return(cursorPageSlice);
        }
コード例 #9
0
 public static string?SerializeCursor(int?index)
 {
     return(index != null
         ? IndexEdge <string> .Create(String.Empty, (int)index)?.Cursor
         : default);