void SimpQEM::updateEdgeCosts(Point* v, int i) { timespec t,t0,t1; //cout << "To|From: " << v->to.size() << "|" << v->from.size() << endl; for(vector<Edge*>::iterator eit = v->from.begin(); eit != v->from.end(); ++ eit) { gettime(t0); if(isEntirelyInCell(*eit) && isCrownInCell((*eit)->p1) && isCrownInCell((*eit)->p2)) { //cerr << "Edge update " << (*eit)->id << " - " << (*eit)->p1->id << " " << (*eit)->p2->id << endl; (*eit)->cost = getCost((*eit)); currentEdgeCost[(*eit)->id] = (*eit)->cost; //pair<int,int> pp((*eit)->p1->id,(*eit)->p2->id); //currentEdgePoints[(*eit)->id] = pp; cell_queue[i].push(*(*eit)); } gettime(t1); t = diff (t0,t1); time_other+=getNanoseconds(t); } for(vector<Edge*>::iterator eit = v->to.begin(); eit != v->to.end(); ++ eit) { gettime(t0); if(isEntirelyInCell(*eit) && isCrownInCell((*eit)->p1) && isCrownInCell((*eit)->p2)) { //cerr << "Edge update " << (*eit)->id << " - " << (*eit)->p1->id << " " << (*eit)->p2->id << endl; (*eit)->cost = getCost((*eit)); currentEdgeCost[(*eit)->id] = (*eit)->cost; //pair<int,int> pp((*eit)->p1->id,(*eit)->p2->id); //currentEdgePoints[(*eit)->id] = pp; cell_queue[i].push(*(*eit)); } gettime(t1); t = diff (t0,t1); time_other+=getNanoseconds(t); } //cout << "Update one edge: " << tcost << endl; }
void bench_division() { std::default_random_engine generator; generator.seed(getNanoseconds()); std::uniform_int_distribution<int> degreeDistrib(0, 255); std::vector<Poly> polys; for (int i = 0; i < 1000; i++) { polys.push_back(Poly::random(degreeDistrib(generator), generator)); } // 1 - Check Correctness of the division { int tries = 0; int successes = 0; for (Poly p1 : polys) { for (Poly p2 : polys) { tries ++; Poly q, r; p1.euclidianDivision(p2, q, r); if ((p1 + q * p2 + r).size() == 0) { successes ++; } } } std::cout << "Division success ratio : (" << successes << "/" << tries << ")" << std::endl; } // 2 - Bench the division { int forceBench = 0; auto start = std::chrono::high_resolution_clock::now(); for (Poly p1 : polys) { for (Poly p2 : polys) { Poly q, r; p1.euclidianDivision(p2, q, r); forceBench += r.degree() + q.degree(); } } auto end = std::chrono::high_resolution_clock::now(); volatile int forceBench2 = forceBench; (void) forceBench2; std::cout << "Division took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; } }
double SimpQEM::getCost(Edge* e) { timespec t,t0,t1; timespec te,te0,te1; gettime(t0); SimpELEN::setPlacement(e); //Error cost is given by vTQv quere v is placement vertex; copyQuadrics(e->placement->Q,e->p1->Q); sumQuadrics(e->placement->Q,e->p2->Q); gettime(t1); t = diff (t0,t1); time_quadrics+=getNanoseconds(t); gettime(te0); double c = getCost(e->placement); gettime(te1); te = diff(te0,te1); time_error += getNanoseconds(te); //cout << "Eid|Cost: " << e->id << "|"<<c<<endl; return c; }
void updateClock(RunTimeOpts *rtOpts, PtpClock *ptpClock) { Integer32 adj=0; TimeInternal timeTmpA; // AKB: Added values for adjusting calc based on time to get time TimeInternal timeTmpB; TimeInternal timeTmpC; TimeInternal timeTmpD; TimeInternal timeTmpE; TimeInternal timeTmpF; Integer64 delta_time_calc; DBGV("updateClock:\n"); if(ptpClock->offset_from_master.seconds) { /* if offset from master seconds is non-zero, then this is a "big jump: * in time. Check Run Time options to see if we will reset the clock or * set frequency adjustment to max to adjust the time */ if(!rtOpts->noAdjust) { if(!rtOpts->noResetClock) { if (!isNonZeroTime(&ptpClock->t1_sync_delta_time)) { // Delta time is zero, so this is the first sync to capture and we'll do the major // adjustment on the next sync instead of this one // // Store t1 and t2 times as current delta, next time we'll subtract // copyTime(&ptpClock->t1_sync_delta_time, &ptpClock->t1_sync_tx_time ); copyTime(&ptpClock->t2_sync_delta_time, &ptpClock->t2_sync_rx_time ); NOTIFY("updateClock: Storing current T1 and T2 values for later calc\n"); DBG("updateClock: Storing T1: %10ds %11dns\n", ptpClock->t1_sync_delta_time.seconds, ptpClock->t1_sync_delta_time.nanoseconds ); DBG("updateClock: Storing T2: %10ds %11dns\n", ptpClock->t2_sync_delta_time.seconds, ptpClock->t2_sync_delta_time.nanoseconds ); return; } // If we are here then t1 and t2 sync delta were set to previous t1 and t2 // values. Now we calculate the deltas DBG("updateClock: Current T1: %10ds %11dns\n", ptpClock->t1_sync_tx_time.seconds, ptpClock->t1_sync_tx_time.nanoseconds ); DBG("updateClock: Current T2: %10ds %11dns\n", ptpClock->t2_sync_rx_time.seconds, ptpClock->t2_sync_rx_time.nanoseconds ); subTime(&ptpClock->t1_sync_delta_time, &ptpClock->t1_sync_tx_time, &ptpClock->t1_sync_delta_time ); subTime(&ptpClock->t2_sync_delta_time, &ptpClock->t2_sync_rx_time, &ptpClock->t2_sync_delta_time ); DBG("updateClock: Delta T1: %10ds %11dns\n", ptpClock->t1_sync_delta_time.seconds, ptpClock->t1_sync_delta_time.nanoseconds ); DBG("updateClock: Delta T2: %10ds %11dns\n", ptpClock->t2_sync_delta_time.seconds, ptpClock->t2_sync_delta_time.nanoseconds ); // Now we get the difference between the two time bases and store in the T2 time delta // as we will use the T1 time as the divisor (so master clock drives the time) subTime(&ptpClock->t2_sync_delta_time, &ptpClock->t2_sync_delta_time, &ptpClock->t1_sync_delta_time ); DBG("updateClock: Delta T2 - Delta T1: %10ds %11dns\n", ptpClock->t2_sync_delta_time.seconds, ptpClock->t2_sync_delta_time.nanoseconds ); delta_time_calc = getNanoseconds(&ptpClock->t2_sync_delta_time) * 1000000000; delta_time_calc /= getNanoseconds(&ptpClock->t1_sync_delta_time); DBG("updateClock: Calculated Parts/billion: %d\n", (int)delta_time_calc ); /* clamp the accumulator to ADJ_FREQ_MAX for sanity */ if( delta_time_calc > ADJ_FREQ_MAX) adj = ADJ_FREQ_MAX; else if(delta_time_calc < -ADJ_FREQ_MAX) adj = -ADJ_FREQ_MAX; else adj = (UInteger32)delta_time_calc; NOTIFY("updateClock: Initial clock adjust: %d, base: %d\n", adj, ptpClock->baseAdjustValue ); NOTIFY("updateClock: Offset from Master %ds.%9.9d seconds\n", ptpClock->offset_from_master.seconds, ptpClock->offset_from_master.nanoseconds ); DBG( "updateClock: offset_from_master seconds != 0\n"); DBGV(" master-to-slave delay: %10ds %11dns\n", ptpClock->master_to_slave_delay.seconds, ptpClock->master_to_slave_delay.nanoseconds ); DBGV(" slave-to-master delay: %10ds %11dns\n", ptpClock->slave_to_master_delay.seconds, ptpClock->slave_to_master_delay.nanoseconds ); DBGV(" one-way delay: %10ds %11dns\n", ptpClock->one_way_delay.seconds, ptpClock->one_way_delay.nanoseconds ); DBG( " offset from master: %10ds %11dns\n", ptpClock->offset_from_master.seconds, ptpClock->offset_from_master.nanoseconds ); DBG( " observed drift: %10d\n", ptpClock->observed_drift ); getTime(&timeTmpA, ptpClock->current_utc_offset); // Get current time #1 getTime(&timeTmpB, ptpClock->current_utc_offset); // Get current time #2 subTime(&timeTmpC, // Calculate time #3, time elapsed between calls &timeTmpB, &timeTmpA ); getTime(&timeTmpD, ptpClock->current_utc_offset); // Get current time #4 subTime(&timeTmpE, // Subtract calculated offset from master &timeTmpD, &ptpClock->offset_from_master ); addTime(&timeTmpF, // Add calculated time to get timer value &timeTmpE, &timeTmpC ); setTime(&timeTmpF, ptpClock->current_utc_offset); // Set new PTP time DBGV(" get Time A : %10ds %11dns\n", timeTmpA.seconds, timeTmpA.nanoseconds ); DBGV(" get Time B : %10ds %11dns\n", timeTmpB.seconds, timeTmpB.nanoseconds ); DBGV(" calc Time C (B-A) : %10ds %11dns\n", timeTmpC.seconds, timeTmpC.nanoseconds ); DBGV(" get Time D : %10ds %11dns\n", timeTmpD.seconds, timeTmpD.nanoseconds ); DBGV(" offset from master : %10ds %11dns\n", ptpClock->offset_from_master.seconds, ptpClock->offset_from_master.nanoseconds ); DBGV(" calc Time E (D+offset): %10ds %11dns\n", timeTmpE.seconds, timeTmpE.nanoseconds ); DBGV(" calc Time F (E+C) : %10ds %11dns\n", timeTmpF.seconds, timeTmpF.nanoseconds ); DBGV("updateClock: set time to Time F\n"); // Initialize clock variables based on run time options (rtOpts) initClockVars(rtOpts, ptpClock); // Adjust clock based on calculation from Delta T1, T2 times adjFreq(ptpClock->baseAdjustValue - adj); // Set initial observed drift to this calculated value ptpClock->observed_drift = adj; DBG( "updateClock: after initClock:\n"); DBGV(" master-to-slave delay: %10ds %11dns\n", ptpClock->master_to_slave_delay.seconds, ptpClock->master_to_slave_delay.nanoseconds ); DBGV(" slave-to-master delay: %10ds %11dns\n", ptpClock->slave_to_master_delay.seconds, ptpClock->slave_to_master_delay.nanoseconds ); DBG( " one-way delay: %10ds %11dns\n", ptpClock->one_way_delay.seconds, ptpClock->one_way_delay.nanoseconds ); DBG( " offset from master: %10ds %11dns\n", ptpClock->offset_from_master.seconds, ptpClock->offset_from_master.nanoseconds ); DBG( " observed drift: %10d\n", ptpClock->observed_drift ); } else { /* Run time options indicate we can't reset the clock, so we slow * it down or speed it up based on ADJ_FREQ_MAX adjustment rather * than actually setting the time. */ adj = ptpClock->offset_from_master.nanoseconds > 0 ? ADJ_FREQ_MAX : -ADJ_FREQ_MAX; adjFreq(ptpClock->baseAdjustValue - adj); } } } else { /* Offset from master is less than one second. Use the the PI controller * to adjust the time */ DBGV("updateClock: using PI controller to update clock\n"); /* no negative or zero attenuation */ if(rtOpts->ap < 1) rtOpts->ap = 1; if(rtOpts->ai < 1) rtOpts->ai = 1; DBGV(" previous observed drift: %10d\n", ptpClock->observed_drift ); DBGV(" run time opts P: %10d\n", rtOpts->ap ); DBGV(" run time opts I: %10d\n", rtOpts->ai ); DBGV(" current observed drift: %d\n", ptpClock->observed_drift ); DBGV(" current offset %dns\n", rtOpts->ai ); /* the accumulator for the I component */ ptpClock->observed_drift += ptpClock->offset_from_master.nanoseconds/rtOpts->ai; DBGV(" new observed drift (I): %d\n", ptpClock->observed_drift ); /* clamp the accumulator to ADJ_FREQ_MAX for sanity */ if( ptpClock->observed_drift > ADJ_FREQ_MAX) ptpClock->observed_drift = ADJ_FREQ_MAX; else if(ptpClock->observed_drift < -ADJ_FREQ_MAX) ptpClock->observed_drift = -ADJ_FREQ_MAX; DBGV(" clamped drift: %d\n", ptpClock->observed_drift ); adj = ptpClock->offset_from_master.nanoseconds/rtOpts->ap + ptpClock->observed_drift; DBGV(" calculated adjust: %d\n", adj ); DBGV(" base adjust: %d\n", ptpClock->baseAdjustValue ); /* apply controller output as a clock tick rate adjustment */ if(!rtOpts->noAdjust) { DBGV(" calling adjFreq with: %d\n", (ptpClock->baseAdjustValue-adj) ); adjFreq(ptpClock->baseAdjustValue - adj); if (rtOpts->rememberAdjustValue == TRUE) { if ( ptpClock->offset_from_master.nanoseconds <= 100 && ptpClock->offset_from_master.nanoseconds >= -100 ) { ptpClock->lastAdjustValue = -adj; // Store value if it gave a good clock // result. } } } } /* Display statistics (save to a file if -f specified) if run time option enabled */ if(rtOpts->displayStats) displayStats(rtOpts, ptpClock); DBGV(" offset from master: %10ds %11dns\n", ptpClock->offset_from_master.seconds, ptpClock->offset_from_master.nanoseconds ); DBGV(" master-to-slave delay: %10ds %11dns\n", ptpClock->master_to_slave_delay.seconds, ptpClock->master_to_slave_delay.nanoseconds ); DBGV(" slave-to-master delay: %10ds %11dns\n", ptpClock->slave_to_master_delay.seconds, ptpClock->slave_to_master_delay.nanoseconds ); DBGV(" one-way delay: %10ds %11dns\n", ptpClock->one_way_delay.seconds, ptpClock->one_way_delay.nanoseconds ); DBGV( " current observed drift: %10d\n", ptpClock->observed_drift ); DBGV(" clock adjust value: %10d\n", (ptpClock->baseAdjustValue - adj) ); }
bool Surface::collapse(Edge& e) { timespec t0,t1,t; clock_gettime(CLOCK_REALTIME,&t0); Point* p1 = e.p1; Point* p2 = e.p2; assert(p1); assert(p2); if(p1->faces.size() ==0 || p2->faces.size()==0) //Do not simplify boundary corners { //cerr << "*ERROR: EMPTY VERTEX.\n"; failed_collapses++; //cout << redtty << "failed.\n" << deftty; return false; } //Iterating faces vector<Face*> for_removal; //clock_gettime(CLOCK_REALTIME,&t0); for(vector<Face*>::iterator fit = p1->faces.begin(); fit!=p1->faces.end(); ++fit) { bool removeface = false; vector<Point*>::iterator auxp1; for(vector<Point*>::iterator pit = (*fit)->points.begin(); pit != (*fit)->points.end() ; ++pit) { if((*pit) == p2) { removeface = true; break; } else if ((*pit) == p1) { auxp1 = pit; } } if(removeface) //p1 and p2 share face, remove it. { for_removal.push_back((*fit)); } else //Swap p1 for p2 for this face { //Face is about to be modified. Checking intersection. Point3 p30((*fit)->points[0]->x,(*fit)->points[0]->y,(*fit)->points[0]->z); Point3 p31((*fit)->points[1]->x,(*fit)->points[1]->y,(*fit)->points[1]->z); Point3 p32((*fit)->points[2]->x,(*fit)->points[2]->y,(*fit)->points[2]->z); Triangle3 face(p30,p31,p32); for(face_vec_it fit2 = m_faces.begin(); fit2 != m_faces.end(); ++fit2) { Face* f = (*fit2); Point3 pf0(f->points[0]->x,f->points[0]->y,f->points[0]->z); Point3 pf1(f->points[1]->x,f->points[1]->y,f->points[1]->z); Point3 pf2(f->points[2]->x,f->points[2]->y,f->points[2]->z); Triangle3 face2(pf0,pf1,pf2); if(CGAL::do_intersect(face,face2)) { cerr << "***Faces " << (*fit)->id << " X " << f->id << endl; } } (*auxp1) = p2; p2->faces.push_back((*fit)); } } //cerr << "Removing faces: "; for(vector<Face*>::iterator it = for_removal.begin(); it != for_removal.end(); ++it) { //cerr << (*it)->id << " "; removeFace(*it); (*it)->removed = true; //delete (*it); } //Set position of p2 as midpoint between p1-p2 p2->x = e.placement->x; p2->y = e.placement->y; p2->z = e.placement->z; clock_gettime(CLOCK_REALTIME,&t1); t = diff(t0,t1); time_faces+= getNanoseconds(t); //TODO: more efficient to use std::remove_if clock_gettime(CLOCK_REALTIME,&t0); removeEdge(m_edges[e.id]); vector<Edge*> edges_to_remove; edge_vec_it eit = p1->to.begin(); //Remove double edges to while(eit != p1->to.end()) { Edge* e = (*eit); bool found = false; edge_vec_it it = p2->to.begin(); while(it != p2->to.end()) { Edge* e2 = (*it); if(e->p1->id == e2->p1->id) { //cerr << "Found " << e->id << " " << e->p1->id << " " << e->p2->id << endl; edges_to_remove.push_back(e); found = true; break; } it++; } if(!found) { e->p2 = p2; if(e->p1->id == e->p2->id) edges_to_remove.push_back(e); } eit++; } //Remove double edges from eit = p1->from.begin(); while(eit!=p1->from.end()) { Edge* e = (*eit); bool found = false; edge_vec_it it = p2->from.begin(); while(it != p2->from.end()) { Edge* e2 = (*it); if(e->p2->id == e2->p2->id) { //cerr << "Found from " << e->id << " " << e->p1->id << " " <<e->p2->id << endl; edges_to_remove.push_back(e); found =true; break; } it++; } if(!found) { e->p1=p2; if(e->p1->id == e->p2->id) edges_to_remove.push_back(e); } eit++; } eit = edges_to_remove.begin(); while(eit != edges_to_remove.end()) { removeEdge(*eit); eit++; } //Append p1 edges to p2 p2->to.insert(p2->to.end(), p1->to.begin(), p1->to.end()); p2->from.insert(p2->from.end(),p1->from.begin(), p1->from.end()); clock_gettime(CLOCK_REALTIME,&t1); t = diff(t0,t1); time_edges += getNanoseconds(t); //Can remove point p1 clock_gettime(CLOCK_REALTIME,&t0); removePoint(p1); clock_gettime(CLOCK_REALTIME,&t1); t = diff(t0,t1); time_point+=getNanoseconds(t); return true; }
void SimpQEM::simplify(int goal, int gridres=1) { cerr << "Initializing edge costs.\n"; time_updating = 0; time_collapsing = 0; time_skipping = 0; time_resetting = 0; time_iterating = 0; failed_pop = 0; failed_removed = 0; failed_cost = 0; edges_outdated = 0; unsigned long time_grid = 0; timespec t0,t1,t,tu,tu0,tu1; timespec tr0,tr1,tr; //time for resetting queue timespec tgrid0,tgrid1,tgrid;//Time for constructing grid clock_gettime(CLOCK_REALTIME, &t0); initQuadrics(); initEdgeCosts(); clock_gettime(CLOCK_REALTIME, &t1); t = diff(t0,t1); cout << greentty << "Time_init_edges: " << getMilliseconds(t) << deftty << endl; int vertices_removed = 0; cerr << orangetty<< "Target vertex count: " << s->m_points.size() - goal << deftty<< endl; clock_gettime(CLOCK_REALTIME, &t0); while(vertices_removed < goal) { clock_gettime(CLOCK_REALTIME,&tgrid0); initUniformGrid(gridres); clock_gettime(CLOCK_REALTIME,&tgrid1); tgrid = diff(tgrid0,tgrid1); time_grid += getNanoseconds(tgrid); cout << greentty << "Grid: " << gridres << endl; cout << lightcyantty << "Removed: " << vertices_removed << endl; cout << lightgreentty << "Time_init_grid: " << getMilliseconds(tgrid) << deftty << endl; omp_set_num_threads(nthreads); #pragma omp parallel for for(int i = 0; i < n_cells; ++i) { int vr = 0; if(cell[i].empty() || cell_queue[i].empty()) continue; //cerr << "Simplifying cell " << i << " - " << cell_queue[i].size() << " edges" << endl; while(vr < initial_vertices[i]/gridres && vertices_removed < goal && !cell_queue[i].empty()) { Edge e = cell_queue[i].top(); cell_queue[i].pop(); //Skip edge if it's been removed or its cost has changed. if(s->is_edge_removed[e.id] || e.cost != currentEdgeCost[e.id] || e.p1->faces.empty() || e.p2->faces.empty()) { //failed_pop++; continue; } double tempQ[4][4]; copyQuadrics(tempQ,e.p1->Q); sumQuadrics(tempQ,e.p2->Q); bool collapsed = s->collapse(e); if(collapsed) { copyQuadrics(e.p2->Q,tempQ); vr++; clock_gettime(CLOCK_REALTIME,&tu0); updateEdgeCosts(e.p2, i); clock_gettime(CLOCK_REALTIME,&tu1); tu = diff(tu0,tu1); time_updating += getNanoseconds(tu); currentEdgeCost[e.id] = INF; // Edge has been removed #pragma omp atomic vertices_removed++; } } //cerr << "Vertices removed: " << vr << endl; } if(gridres>=2) gridres/=2; } clock_gettime(CLOCK_REALTIME, &t1); t = diff(t0,t1); cout << bluetty << "Time_simplify: " << getNanoseconds(t)/1000000 << deftty << endl; cout << bluetty << "Time_updating: " << time_updating/1000000 << deftty << endl; cout << yellowtty << "Time_get_error: " << time_error/1000000 << deftty << endl; cout << lightbluetty << "Time_quadrics: " << time_quadrics/1000000 << deftty << endl; cout << lightpurpletty << "Time_other: " << time_other/1000000 << deftty << endl; // cout << yellowtty << "Time_iterating: " << time_iterating/1000000 << deftty << endl; // cout << lightbluetty << "Time_collapsing: " << time_collapsing/1000000 << deftty << endl; // cout << lightpurpletty << "\tRemoving faces: " << s->time_faces/1000000 << deftty<<endl; // cout << lightpurpletty << "\tRemoving edges: " << s->time_edges/1000000 << deftty<<endl; // cout << lightpurpletty << "\tRemoving points: " << s->time_point/1000000 << deftty<<endl; // cout << redtty << "Time skipping: " << time_skipping/1000000 << deftty << endl; // cout << cyantty << "Time resetting queue: " << time_resetting/1000000 << deftty << endl; // cout << lightredtty << "Failed pops: " << failed_pop << " " << failed_removed << "(removed) - " << failed_cost << "(cost)" << deftty<<endl; // cout << lightredtty << "Failed collapses: " << s->failed_collapses << deftty << endl; cout << cyantty << "Left in queue: " << edge_queue.size() << deftty << endl; }
int64_t getMicroseconds() const { return int64_t(0.5 + getNanoseconds() / 1000.0); }
void bench_multiply() { std::default_random_engine generator; generator.seed(getNanoseconds()); std::uniform_int_distribution<int> degreeDistrib(0, 255); std::vector<Poly> polys; for (int i = 0; i < 1000; i++) { polys.push_back(Poly::random(degreeDistrib(generator), generator)); } // 1 - Check Correctness of karatsubas { int tries = 0; int successes = 0; for (Poly p : polys) { for (Poly q : polys) { if (p.degree() + q.degree() >= 256) { continue; } tries ++; Poly res1 = p.multiplyNaively(q); Poly res2 = p.multiplyKaratsuba32(q); if ((res1 + res2).size() == 0) { successes ++; } } } std::cout << "Karatsuba32 success ratio : (" << successes << "/" << tries << ")" << std::endl; } // 2 - Bench the naive method { int forceBench = 0; auto start = std::chrono::high_resolution_clock::now(); for (Poly p : polys) { for (Poly q : polys) { if (p.degree() + q.degree() >= 256) { continue; } Poly r = p.multiplyNaively(q); forceBench += r.degree(); } } auto end = std::chrono::high_resolution_clock::now(); volatile int forceBench2 = forceBench; (void) forceBench2; std::cout << "Naive took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; } // 3 - Bench the karatsuba32 method { int forceBench = 0; auto start = std::chrono::high_resolution_clock::now(); for (Poly p : polys) { for (Poly q : polys) { if (p.degree() + q.degree() >= 256) { continue; } Poly r = p.multiplyKaratsuba32(q); forceBench += r.degree(); } } auto end = std::chrono::high_resolution_clock::now(); volatile int forceBench2 = forceBench; (void) forceBench2; std::cout << "Karatsuba32 took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; } }
void bench_shifts() { std::default_random_engine generator; generator.seed(getNanoseconds()); std::uniform_int_distribution<int> degreeDistrib(0, 255); std::vector<Poly> polys; for (int i = 0; i < 10000; i++) { polys.push_back(Poly::random(degreeDistrib(generator), generator)); } // 1 - Check Correctness of shifts { int tries = 0; int successes = 0; for (Poly p : polys) { for (unsigned i = 0; i < 256 - p.size(); i++) { tries ++; Poly res1 = naiveShiftLeft(p, i); Poly res2 = p << i; if ((res1 + res2).size() == 0) { successes ++; } } for (unsigned i = 0; i <= p.size(); i++) { tries ++; Poly res1 = naiveShiftRight(p, i); Poly res2 = p >> i; if ((res1 + res2).size() == 0) { successes ++; } } } std::cout << "Shifts success ratio : (" << successes << "/" << tries << ")" << std::endl; } // 2 - Bench the naive method { int forceBench = 0; auto start = std::chrono::high_resolution_clock::now(); for (Poly p : polys) { for (unsigned i = 0; i < 256 - p.size(); i++) { Poly r = naiveShiftLeft(p, i); forceBench += r.degree(); } for (unsigned i = 0; i <= p.size(); i++) { Poly r = naiveShiftRight(p, i); forceBench += r.degree(); } } auto end = std::chrono::high_resolution_clock::now(); volatile int forceBench2 = forceBench; (void) forceBench2; std::cout << "Naive took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; } // 3 - Bench the fast method { int forceBench = 0; auto start = std::chrono::high_resolution_clock::now(); for (Poly p : polys) { for (unsigned i = 0; i < 256 - p.size(); i++) { Poly r = p << i; forceBench += r.degree(); } for (unsigned i = 0; i <= p.size(); i++) { Poly r = p >> i; forceBench += r.degree(); } } auto end = std::chrono::high_resolution_clock::now(); volatile int forceBench2 = forceBench; (void) forceBench2; std::cout << "Naive took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl; } }