void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_protection, const char *language, const char *label, bool _enforce_wordlist) { if (_word_count != 12 && _word_count != 18 && _word_count != 24) { fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid word count (has to be 12, 18 or 24 bits)"); layoutHome(); return; } word_count = _word_count; enforce_wordlist = _enforce_wordlist; if (pin_protection && !protectChangePin()) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "PIN change failed"); layoutHome(); return; } storage.has_passphrase_protection = true; storage.passphrase_protection = passphrase_protection; storage_setLanguage(language); storage_setLabel(label); uint32_t i; for (i = 0; i < word_count; i++) { word_order[i] = i + 1; } for (i = word_count; i < 24; i++) { word_order[i] = 0; } random_permute(word_order, 24); awaiting_word = true; word_index = 0; next_word(); }
// Prepare a list of points for Delaunay triangulation: randomly assign into logarithmic bins, sort within bins, and add sentinels. // For details, see Amenta et al., Incremental Constructions con BRIO. static Array<Perturbed2> partially_sorted_shuffle(RawArray<const EV> Xin) { const int n = Xin.size(); Array<Perturbed2> X(n+3,uninit); // Randomly assign input points into bins. Bin k has 2**k = 1,2,4,8,... and starts at index 2**k-1 = 0,1,3,7,... // We fill points into bins as sequentially as possible to maximize cache coherence. const int bins = integer_log(n); Array<int> bin_counts(bins); for (int i=0;i<n;i++) { int j = (int)random_permute(n,key,i); const int bin = min(integer_log(j+1),bins-1); j = (1<<bin)-1+bin_counts[bin]++; X[j] = Perturbed2(i,Xin[i]); } // Spatially sort each bin down to clusters of size 64. const int leaf_size = 64; for (int bin=0;bin<bins;bin++) { const int start = (1<<bin)-1, end = bin==bins-1?n:start+(1<<bin); assert(bin_counts[bin]==end-start); spatial_sort(X.slice(start,end),leaf_size,new_<Random>(key+bin)); } // Add 3 sentinel points at infinity X[n+0] = Perturbed2(n+0,EV(-bound,-bound)); X[n+1] = Perturbed2(n+1,EV( bound, 0) ); X[n+2] = Perturbed2(n+2,EV(-bound, bound)); return X; }
void pinmatrix_start(const char *text) { int i; for (i = 0; i < 9; i++) { pinmatrix_perm[i] = '1' + i; } pinmatrix_perm[9] = 0; random_permute(pinmatrix_perm, 9); pinmatrix_draw(text); }
void test_groups_noncollective() { int *pid_lists[MAX_GROUPS]; int pids[MAXPROC]; int i, nprocs, world_me; ARMCI_Group group; int *my_pid_list=NULL, my_grp_size=0; int ngrps; MP_BARRIER(); MP_PROCS(&nprocs); MP_MYID(&world_me); random_permute(pids, nproc); ngrps = nprocs/GROUP_SIZE; for(i=0; i<nprocs/GROUP_SIZE; i++) { pid_lists[i] = pids + (i*GROUP_SIZE); } for(i=0; i<nprocs; i++) { if(pids[i] == world_me) { int grp_id = ARMCI_MIN(i/GROUP_SIZE, ngrps-1); my_pid_list = pid_lists[grp_id]; if(grp_id == ngrps-1) my_grp_size = GROUP_SIZE + (nprocs%GROUP_SIZE); else my_grp_size = GROUP_SIZE; } } qsort(my_pid_list, my_grp_size, sizeof(int), int_compare); MP_BARRIER(); /*now create all these disjoint groups and test them in parallel*/ ARMCI_Group_create(my_grp_size, my_pid_list, &group); test_one_group(&group, my_pid_list); ARMCI_Group_free(&group); ARMCI_AllFence(); MP_BARRIER(); if(world_me==0){printf("O.K.\n"); fflush(stdout);} }
// Greedily compute a set of nonintersecting edges in a point cloud for testing purposes // Warning: Takes O(n^3) time. static Array<Vector<int,2>> greedy_nonintersecting_edges(RawArray<const Vector<real,2>> X, const int limit) { const auto E = amap(quantizer(bounding_box(X)),X).copy(); const int n = E.size(); Array<Vector<int,2>> edges; IntervalScope scope; for (const int i : range(n*n)) { const int pi = int(random_permute(n*n,key+14,i)); const int a = pi/n, b = pi-n*a; if (a < b) { const auto Ea = Perturbed2(a,E[a]), Eb = Perturbed2(b,E[b]); for (const auto e : edges) if (!e.contains(a) && !e.contains(b) && segments_intersect(Ea,Eb,Perturbed2(e.x,E[e.x]),Perturbed2(e.y,E[e.y]))) goto skip; edges.append(vec(a,b)); if (edges.size()==limit || edges.size()==3*n-6) break; skip:; } } return edges; }
GEODE_NEVER_INLINE static void add_constraint_edges(MutableTriangleTopology& mesh, RawField<const EV,VertexId> X, RawArray<const Vector<int,2>> edges, const bool validate) { if (!edges.size()) return; IntervalScope scope; Hashtable<Vector<VertexId,2>> constrained; Array<VertexId> left_cavity, right_cavity; // List of vertices for both cavities const auto random = new_<Random>(key+7); for (int i=0;i<edges.size();i++) { // Randomly choose an edge to ensure optimal time complexity const auto edge = edges[int(random_permute(edges.size(),key+5,i))].sorted(); auto v0 = VertexId(edge.x), v1 = VertexId(edge.y); const auto vs = vec(v0,v1); GEODE_ASSERT(mesh.valid(v0) && mesh.valid(v1)); { // Check if the edge already exists in the triangulation. To ensure optimal complexity, // we loop around both vertices interleaved so that our time is O(min(degree(v0),degree(v1))). const auto s0 = mesh.halfedge(v0), s1 = mesh.halfedge(v1); { auto e0 = s0, e1 = s1; do { if (mesh.dst(e0)==v1 || mesh.dst(e1)==v0) goto success; // The edge already exists, so there's nothing to be done. e0 = mesh.left(e0); e1 = mesh.left(e1); } while (e0!=s0 && e1!=s1); } // Find a triangle touching v0 or v1 containing part of the v0-v1 segment. // As above, we loop around both vertices interleaved. auto e0 = s0; { auto e1 = s1; if (mesh.is_boundary(e0)) e0 = mesh.left(e0); if (mesh.is_boundary(e1)) e1 = mesh.left(e1); const auto x0 = Perturbed2(v0.id,X[v0]), x1 = Perturbed2(v1.id,X[v1]); const auto e0d = mesh.dst(e0), e1d = mesh.dst(e1); bool e0o = triangle_oriented(x0,Perturbed2(e0d.id,X[e0d]),x1), e1o = triangle_oriented(x1,Perturbed2(e1d.id,X[e1d]),x0); for (;;) { // No need to check for an end condition, since we're guaranteed to terminate const auto n0 = mesh.left(e0), n1 = mesh.left(e1); const auto n0d = mesh.dst(n0), n1d = mesh.dst(n1); const bool n0o = triangle_oriented(x0,Perturbed2(n0d.id,X[n0d]),x1), n1o = triangle_oriented(x1,Perturbed2(n1d.id,X[n1d]),x0); if (e0o && !n0o) break; if (e1o && !n1o) { // Swap v0 with v1 and e0 with e1 so that our ray starts at v0 swap(v0,v1); swap(e0,e1); break; } e0 = n0; e1 = n1; e0o = n0o; e1o = n1o; } } // If we only need to walk one step, the retriangulation is a single edge flip auto cut = mesh.reverse(mesh.next(e0)); if (mesh.dst(mesh.next(cut))==v1) { if (constrained.contains(vec(mesh.src(cut),mesh.dst(cut)).sorted())) throw DelaunayConstraintConflict(vec(v0.id,v1.id),vec(mesh.src(cut).id,mesh.dst(cut).id)); cut = mesh.flip_edge(cut); goto success; } // Walk from v0 to v1, collecting the two cavities. const auto x0 = Perturbed2(v0.id,X[v0]), x1 = Perturbed2(v1.id,X[v1]); right_cavity.copy(vec(v0,mesh.dst(cut))); left_cavity .copy(vec(v0,mesh.src(cut))); mesh.erase(mesh.face(e0)); for (;;) { if (constrained.contains(vec(mesh.src(cut),mesh.dst(cut)).sorted())) throw DelaunayConstraintConflict(vec(v0.id,v1.id),vec(mesh.src(cut).id,mesh.dst(cut).id)); const auto n = mesh.reverse(mesh.next(cut)), p = mesh.reverse(mesh.prev(cut)); const auto v = mesh.src(n); mesh.erase(mesh.face(cut)); if (v == v1) { left_cavity.append(v); right_cavity.append(v); break; } else if (triangle_oriented(x0,x1,Perturbed2(v.id,X[v]))) { left_cavity.append(v); cut = n; } else { right_cavity.append(v); cut = p; } } // Retriangulate both cavities left_cavity.reverse(); cavity_delaunay(mesh,X,left_cavity,random), cavity_delaunay(mesh,X,right_cavity,random); } success: constrained.set(vs); } // If desired, check that the final mesh is constrained Delaunay if (validate) assert_delaunay("constrained delaunay validate: ",mesh,X,constrained); }