int main(int argc, char* argv[]) { glutInit(&argc, argv); // default configuration filename const char* configFilename = "test.edl"; // build a test station testStation = builder(configFilename); // resetting the system will load the data files std::cout << "starting loading files --" << std::endl; const double start = getComputerTime(); testStation->reset(); const double end = getComputerTime(); const double dtime = (end - start); std::cout << "finished loading files: time(s) = " << dtime << std::endl; // set timer for background tasks const double dt = 1.0/static_cast<double>(bgRate); const unsigned int millis = static_cast<unsigned int>(dt * 1000); glutTimerFunc(millis, updateDataCB, 1); testStation->createTimeCriticalProcess(); glutMainLoop(); return 0; }
int main(int argc, char* argv[]) { // default configuration filename const char* configFilename = "test1.edl"; for (int i = 1; i < argc; i++) { if (std::strcmp(argv[i],"-f") == 0) { configFilename = argv[++i]; } } // station = builder(configFilename); // send a reset event and frame sim once station->event(Basic::Component::RESET_EVENT); station->tcFrame( static_cast<LCreal>(1.0/static_cast<double>(station->getTimeCriticalRate())) ); // create time critical thread station->createTimeCriticalProcess(); // short pause to allow os to startup thread lcSleep(2000); // calculate delta time for background thread double dt = 1.0/static_cast<double>(bgRate); // system time of day double simTime = 0.0; // Simulator time reference double startTime = getComputerTime(); // Time of day (sec) run started //int k = 0; std::cout << "Starting background main loop ..." << std::endl; for(;;) { // update background thread station->updateData( static_cast<LCreal>(dt) ); simTime += dt; // time of next frame double timeNow = getComputerTime(); // time now double elapsedTime = timeNow - startTime; double nextFrameStart = simTime - elapsedTime; int sleepTime = static_cast<int>(nextFrameStart*1000.0); // wait for the next frame if (sleepTime > 0) lcSleep(sleepTime); /* std::cout << "."; k += 1; if ( k == 40 ) { std::cout << "\n"; k = 0; } */ } return 0; }
int main(int argc, char* argv[]) { glutInit(&argc, argv); // default configuration filename const char* configFilename = "test.edl"; // build a display display = builder(configFilename); // resetting the system will load the data files std::cout << "starting loading files --" << std::endl; double start = getComputerTime(); display->reset(); double end = getComputerTime(); double dtime = (end - start); std::cout << "finished loading files: time(s) = " << dtime << std::endl; // create a display window display->createWindow(); // set timer double dt = 1.0/static_cast<double>(frameRate); unsigned int millis = static_cast<unsigned int>(dt * 1000); glutTimerFunc(millis, timerFunc, 1); glutMainLoop(); return 0; }
//------------------------------------------------------------------------------ // dynamics() -- Age queues //------------------------------------------------------------------------------ void Datalink::dynamics(const LCreal) { //age queues Eaagles::Basic::Object* tempInQueue[MAX_MESSAGES]; int numIn = 0; Eaagles::Simulation::Message *msg = 0; while((numIn < MAX_MESSAGES) && inQueue->isNotEmpty()) { Eaagles::Basic::Object* tempObj = inQueue->get(); msg = dynamic_cast<Eaagles::Simulation::Message*>(tempObj); if(msg != 0) { if(getComputerTime() - msg->getTimeStamp() > msg->getLifeSpan()) { //remove message by not adding to list to be put back into queue msg->unref(); } else { tempInQueue[numIn++] = msg; } } else if(tempObj != 0) { tempInQueue[numIn++] = tempObj; } } if(numIn != 0) { for(int i = 0; i < numIn; i++) { inQueue->put(tempInQueue[i]); } } Eaagles::Basic::Object* tempOutQueue[MAX_MESSAGES]; int numOut = 0; msg = 0; while((numOut < MAX_MESSAGES) && outQueue->isNotEmpty()) { Eaagles::Basic::Object* tempObj = outQueue->get(); msg = dynamic_cast<Eaagles::Simulation::Message*>(tempObj); if(msg != 0) { if(getComputerTime() - msg->getTimeStamp() > msg->getLifeSpan()) { //remove message by not adding to list to be put back into queue msg->unref(); } else { tempOutQueue[numOut++] = msg; } } else if(tempObj != 0) { tempOutQueue[numOut++] = tempObj; } } if(numOut != 0) { for(int i = 0; i < numOut; i++) { outQueue->put(tempOutQueue[i]); } } }
//----------------------------------------------------------------------------- // GLUT idle time; static callback function //----------------------------------------------------------------------------- void GlutDisplay::idleCB() { int id = glutGetWindow(); double time = getComputerTime(); // N-1 Time static double time0 = time; // Compute delta time double dt = (time - time0); time0 = time; // Update displays unsigned int sleepFor = DEFAULT_IDLE_SLEEP; for (int i = 0; i < numGlutDisplays; i++) { if (idList[i] >= 0) { glutSetWindow(idList[i]); displayList[i]->updateData( static_cast<LCreal>(dt) ); if (displayList[i]->isMainDisplay()) { sleepFor = displayList[i]->getIdleSleepTime(); } displayList[i]->drawIt(); } } glutSetWindow(id); // Sleep to let other's use the CPU lcSleep(sleepFor); }
//------------------------------------------------------------------------------ // tcFrame() -- Main time-critical frame //------------------------------------------------------------------------------ void Component::tcFrame(const double dt) { // --- // Collect start time // --- double tcStartTime = 0.0; if (isTimingStatsEnabled()) { #if defined(WIN32) LARGE_INTEGER fcnt; QueryPerformanceCounter(&fcnt); tcStartTime = static_cast<double>( fcnt.QuadPart ); #else tcStartTime = getComputerTime(); #endif } // --- // Execute one time-critical frame // --- this->updateTC(dt); // --- // Process timing data // --- if (isTimingStatsEnabled()) { double dtime = 0; // Delta time in MS #if defined(WIN32) LARGE_INTEGER cFreq; QueryPerformanceFrequency(&cFreq); auto freq = static_cast<double>( cFreq.QuadPart ); LARGE_INTEGER fcnt; QueryPerformanceCounter(&fcnt); const auto endCnt = static_cast<double>( fcnt.QuadPart ); double dcnt = endCnt - tcStartTime; dtime = (dcnt/freq) * 1000.0; #else dtime = (getComputerTime() - tcStartTime) * 1000.0; #endif timingStats->sigma(dtime); // Time in MS if (isTimingStatsPrintEnabled()) { printTimingStats(); } } }
//----------------------------------------------------------------------------- // Eaagles::Swarms::main() -- Main routine //----------------------------------------------------------------------------- void exec(int argc, char* argv[]) { // parse arguments for (int i = 1; i < argc; i++) { if (strcmp(argv[i],"-f") == 0) { configFile = argv[++i]; } } // build a Station builder(); // Reset the Simulation station->event(Basic::Component::RESET_EVENT); // Set timer for the background tasks station->tcFrame( static_cast<LCreal>(1.0/static_cast<double>(station->getTimeCriticalRate())) ); // Create the Time Critical Thread station->createTimeCriticalProcess(); // short pause to allow os to startup thread lcSleep(2000); // Calc delta time for background thread double dt = 1.0/static_cast<double>(bgRate); // System Time of Day double simTime = 0.0; // Simulator time reference double startTime = getComputerTime(); // Time of day (sec) run started //cout << "Simulation running..." << endl; while (true) { // runs for 10 minutes // Update background thread station->updateData(static_cast<LCreal>(dt)); simTime += dt; // time of next frame double timeNow = getComputerTime(); // time now double elapsedTime = timeNow - startTime; double nextFrameStart = simTime - elapsedTime; int sleepTime = static_cast<int>(nextFrameStart*1000.0); // wait for the next frame if (sleepTime > 0) lcSleep(sleepTime); } }
//----------------------------------------------------------------------------- // Station's background tasks -- a callback from a GLUT timer, it's basically the // top level of our background thread. (Note: GlutDisplay will handle the // background thread, updateData, for all of its graphics components) //----------------------------------------------------------------------------- static void updateDataCB(int) { const double dt0 = 1.0 / static_cast<double>(bgRate); const unsigned int millis = static_cast<unsigned int>(dt0 * 1000); glutTimerFunc(millis, updateDataCB, 1); // current time const double time = getComputerTime(); // N-1 Time static double time0 = time; // compute delta time const LCreal dt = static_cast<LCreal>(time - time0); time0 = time; station->updateData(dt); }
//----------------------------------------------------------------------------- // Station's background tasks -- a callback from a GLUT timer, it's the // top level of our background thread. (Note: GlutDisplay will handle the // background thread, updateData, for all of its graphics components) //----------------------------------------------------------------------------- static void updateDataCB(int) { double dt0 = 1.0/static_cast<double>(bgRate); unsigned int millis = static_cast<unsigned int>(dt0 * 1000); glutTimerFunc(millis, updateDataCB, 1); // Current time double time = getComputerTime(); // N-1 Time static double time0 = time; // Compute delta time LCreal dt = static_cast<LCreal>(time - time0); time0 = time; Basic::Timer::updateTimers(dt); BasicGL::Graphic::flashTimer(dt); testStation->updateData(dt); }
static void timerCB(int) { const double dt0 = 1.0 / static_cast<double>(frameRate); const unsigned int millis = static_cast<unsigned int>(dt0 * 1000); glutTimerFunc(millis, timerCB, 1); // current time const double time = getComputerTime(); // N-1 Time static double time0 = time; // compute delta time const double dt = (time - time0); time0 = time; Basic::Timer::updateTimers(static_cast<LCreal>(dt)); BasicGL::Graphic::flashTimer(static_cast<LCreal>(dt)); board->tcFrame(static_cast<LCreal>(dt)); }
// timer function, in this case, the background (updateData) function static void timerFunc(int) { const double dt0 = 1.0 / static_cast<double>(frameRate); const unsigned int millis = static_cast<unsigned int>(dt0 * 1000); glutTimerFunc(millis, timerFunc, 1); // Current time const double time = getComputerTime(); // N-1 Time static double time0 = time; // Compute delta time const LCreal dt = static_cast<LCreal>(time - time0); time0 = time; Basic::Timer::updateTimers(dt); BasicGL::Graphic::flashTimer(dt); station->updateData(dt); }
//------------------------------------------------------------------------------ // drawFunc() //------------------------------------------------------------------------------ void Display::drawFunc() { if (image != nullptr) { if (testTexture) { // --- // Draw using texture map // --- // enable textures, if we need to glEnable(GL_TEXTURE_2D); if (texture == 0) { glGenTextures(1,&texture); } // set our texture environment glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); double start = getComputerTime(); glTexImage2D(GL_TEXTURE_2D, 0, PIXEL_SIZE, imgWidth, imgHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image); glBegin(GL_POLYGON); glTexCoord2f( 1.0f, 1.0f ); glVertex2f( 1.0f, 1.0f ); glTexCoord2f( 0.0f, 1.0f ); glVertex2f( 0.0f, 1.0f ); glTexCoord2f( 0.0f, 0.0f ); glVertex2f( 0.0f, 0.0f ); glTexCoord2f( 1.0f, 0.0f ); glVertex2f( 1.0f, 0.0f ); glEnd(); double end = getComputerTime(); double dtime = (end - start); std::cout << "glTexImage2D() dtime = " << dtime << std::endl; glDisable(GL_TEXTURE_2D); } else { // --- // Draw using glDrawPixels() // --- glRasterPos2f(0.0, 0.0); double start = getComputerTime(); glDrawPixels(imgWidth, imgHeight, GL_RGB, GL_UNSIGNED_BYTE, image); double end = getComputerTime(); double dtime = (end - start); std::cout << "glDrawPixels() dtime = " << dtime << std::endl; } } }
//------------------------------------------------------------------------------ // updateData() -- update background data here //------------------------------------------------------------------------------ void Display::updateData(const LCreal dt) { // Get Viewport width and height GLsizei vpWidth = 0; GLsizei vpHeight = 0; getViewportSize(&vpWidth, &vpHeight); // Generate an image when we have the terrain, a view port and we don't have an image if ( terrain != nullptr && terrain->isDataLoaded() && vpWidth > 0 && vpHeight > 0 && image == nullptr) { GLsizei vpWidth = 1024; // default is texture sizes GLsizei vpHeight = 1024; if (!testTexture) { // When not using textures, get the viewport parameters // Get the maximum number of points GLint vpX, vpY; getViewport(&vpX, &vpY, &vpWidth, &vpHeight); // Make sure width is correct for a 4 byte alignment GLsizei w0 = (vpWidth*PIXEL_SIZE); GLsizei w4 = (w0/4)*4; // Truncate to 4 bytes vpWidth = w4/PIXEL_SIZE; } // Allocate the image memory bool ok = initImageMemory(vpWidth, vpHeight); if (ok) { const int NUM_COLUMNS = imgWidth; const int NUM_ROWS = imgHeight; // Allocating space for 'multi-point' tests LCreal* elevations = nullptr; LCreal* aacData = nullptr; bool* validFlgs = nullptr; bool* maskFlgs = nullptr; if (testShadows || testAac || testEarthCurv) { elevations = new LCreal[NUM_ROWS]; aacData = new LCreal[NUM_ROWS]; validFlgs = new bool[NUM_ROWS]; maskFlgs = new bool[NUM_ROWS]; } // Max elevation (Z) value (meters) LCreal maxz = terrain->getMaxElevation(); if (isMaxElevValid()) maxz = getMaxElevation(); // Min elevation (Z) value (meters) LCreal minz = terrain->getMinElevation(); if (isMinElevValid()) minz = getMinElevation(); // Delta altitude (meters) // LCreal deltaElev = maxz - minz + 1; // Compute delta (range of) latitude and longitude double deltaLat = terrain->getLatitudeNE() - terrain->getLatitudeSW(); double deltaLon = terrain->getLongitudeNE() - terrain->getLongitudeSW(); // Compute center position (degs) double cLat = terrain->getLatitudeSW() + deltaLat / 2.0; double cLon = terrain->getLongitudeSW() + deltaLon / 2.0; // Compute distance between points with zoom factor (degs) double spacingLat = deltaLat / NUM_ROWS; double spacingLon = deltaLon / NUM_COLUMNS; // Generate the earth's curvature effect LCreal* curvature =nullptr; if (testEarthCurv) { curvature = new LCreal[NUM_ROWS]; LCreal radius = static_cast<LCreal>(Basic::Nav::ERAD60 * Basic::Distance::NM2M); LCreal maxRng = static_cast<LCreal>(deltaLat * 60.0f * Basic::Distance::NM2M); for (int irow = 0; irow < NUM_ROWS; irow++) { LCreal curRng = maxRng * static_cast<LCreal>(irow)/static_cast<LCreal>(NUM_ROWS); LCreal arc = curRng / radius; LCreal cs = 1.0f; LCreal c0 = lcCos(arc); if (c0 != 0) cs = 1.0f/c0; curvature[irow] = radius * (cs - 1.0f); } } const Basic::Hsva* grayTable[2]; // hue sat value alpha grayTable[0] = new Basic::Hsva( 120.0f, 0.0f, 0.0f, 1.0f ); // black0 grayTable[1] = new Basic::Hsva( 120.0f, 0.0f, 1.0f, 1.0f ); // white0 const Basic::Hsva* colorTable[7]; // hue sat value alpha colorTable[0] = new Basic::Hsva( 240.0f, 1.0f, 1.0f, 1.0f ); // blue colorTable[1] = new Basic::Hsva( 180.0f, 1.0f, 1.0f, 1.0f ); // cyan colorTable[2] = new Basic::Hsva( 120.0f, 1.0f, 1.0f, 1.0f ); // green colorTable[3] = new Basic::Hsva( 60.0f, 1.0f, 1.0f, 1.0f ); // yellow colorTable[4] = new Basic::Hsva( 0.0f, 1.0f, 1.0f, 1.0f ); // red colorTable[5] = new Basic::Hsva( 300.0f, 1.0f, 1.0f, 1.0f ); // magenta colorTable[6] = new Basic::Hsva( 300.0f, 0.05f, 1.0f, 1.0f ); // white0 const Basic::Hsva* greenTable[19]; // hue sat value alpha greenTable[0] = new Basic::Hsva( 120.0f, 1.0f, 0.0f, 1.0f ); greenTable[1] = new Basic::Hsva( 120.0f, 1.0f, 0.0872f, 1.0f ); greenTable[2] = new Basic::Hsva( 120.0f, 1.0f, 0.1736f, 1.0f ); greenTable[3] = new Basic::Hsva( 120.0f, 1.0f, 0.2588f, 1.0f ); greenTable[4] = new Basic::Hsva( 120.0f, 1.0f, 0.3420f, 1.0f ); greenTable[5] = new Basic::Hsva( 120.0f, 1.0f, 0.4226f, 1.0f ); greenTable[6] = new Basic::Hsva( 120.0f, 1.0f, 0.5000f, 1.0f ); greenTable[7] = new Basic::Hsva( 120.0f, 1.0f, 0.5736f, 1.0f ); greenTable[8] = new Basic::Hsva( 120.0f, 1.0f, 0.6428f, 1.0f ); greenTable[9] = new Basic::Hsva( 120.0f, 1.0f, 0.7071f, 1.0f ); greenTable[10] = new Basic::Hsva( 120.0f, 1.0f, 0.7660f, 1.0f ); greenTable[11] = new Basic::Hsva( 120.0f, 1.0f, 0.8192f, 1.0f ); greenTable[12] = new Basic::Hsva( 120.0f, 1.0f, 0.8660f, 1.0f ); greenTable[13] = new Basic::Hsva( 120.0f, 1.0f, 0.9063f, 1.0f ); greenTable[14] = new Basic::Hsva( 120.0f, 1.0f, 0.9397f, 1.0f ); greenTable[15] = new Basic::Hsva( 120.0f, 1.0f, 0.9659f, 1.0f ); greenTable[16] = new Basic::Hsva( 120.0f, 1.0f, 0.9848f, 1.0f ); greenTable[17] = new Basic::Hsva( 120.0f, 1.0f, 0.9962f, 1.0f ); greenTable[18] = new Basic::Hsva( 120.0f, 1.0f, 1.0f, 1.0f ); std::cout << "start image generation" << std::endl; double start = getComputerTime(); for (int icol = 0; icol < NUM_COLUMNS; icol++) { // int halfway = NUM_COLUMNS / 2; // the Lat/long of the southern most point double longitude = cLon + (icol - NUM_COLUMNS/2) * spacingLon; if (testShadows || testAac || testEarthCurv) { for (int irow = 0; irow < NUM_ROWS; irow++) { elevations[irow] = 0; aacData[irow] = 1.0f; validFlgs[irow] = false; maskFlgs[irow] = false; } // the Lat/long of the southern most point double latitude = cLat + (0 - NUM_ROWS/2) * spacingLat; LCreal maxRng = static_cast<LCreal>(deltaLat * 60.0f * Basic::Distance::NM2M); // Direction //LCreal direction = 30.0f * static_cast<LCreal>(icol - NUM_COLUMNS/2)/static_cast<LCreal>(NUM_COLUMNS/2); LCreal direction = 0; // get a strip of elevations from south to north unsigned int num = terrain->getElevations(elevations, validFlgs, NUM_ROWS, latitude, longitude, direction, maxRng, interpolate); // Apply earth curvature effects to terrain elevations if (testEarthCurv) { for (int irow = 0; irow < NUM_ROWS; irow++) { elevations[irow] -= curvature[irow]; } } // Generate Masks if (testShadows) { Basic::Terrain::vbwShadowChecker(maskFlgs, elevations, validFlgs, NUM_ROWS, maxRng, altitude, lookAngle, beamWidth); } // Compute AAC data if (testAac) { //Simulation::Terrain::aac(aacData, elevations, maskFlgs, NUM_ROWS, maxRng, altitude); LCreal angle = static_cast<LCreal>(-10.0f * Basic::Angle::D2RCC); osg::Vec2 vec(lcCos(angle),lcSin(angle)); Basic::Terrain::cLight(aacData, elevations, maskFlgs, NUM_ROWS, maxRng, vec); } } // Draw a line along the Y points (moving from south to north along the latitude lines) for (int irow = 0; irow < NUM_ROWS; irow++) { osg::Vec3 color(0,0,0); LCreal elev = 0; bool valid = false; if (testShadows || testAac || testEarthCurv) { // multi-point test: get the elevation from the array if (validFlgs[irow]) { elev = elevations[irow]; valid = true; } } else { // Single point test: compute the latitude of this point and get the elevation double latitude = cLat + (irow - NUM_ROWS/2) * spacingLat; valid = terrain->getElevation(&elev, latitude, longitude, interpolate); } // If valid and not masked, convert the elevation to a color (or gray) value if (valid && !(testShadows && maskFlgs[irow])) { if (colorScale == GRAY_SCALE) Basic::Terrain::getElevationColor(elev, minz, maxz, grayTable, 2, color); else if (colorScale == COLOR_SCALE) Basic::Terrain::getElevationColor(elev, minz, maxz, colorTable, 7, color); else if (colorScale == GREEN_SCALE) Basic::Terrain::getElevationColor(elev, minz, maxz, greenTable, 19, color); } // Apply AAC data if (valid && testAac) { color = color * aacData[irow]; } //if (icol == 100) { // std::cout << icol << ", " << irow << " = " << elev << " [ " << color.x() << ", " << color.y() << ", " << color.z() << " ]" << std::endl; //} // store this color GLsizei idx = irow*imgWidth*PIXEL_SIZE + icol*PIXEL_SIZE; image[idx+0] = GLubyte( 255.0 * color[0] ); image[idx+1] = GLubyte( 255.0 * color[1] ); image[idx+2] = GLubyte( 255.0 * color[2] ); } } double end = getComputerTime(); double dtime = (end - start); std::cout << "Image finished: time(s) = " << dtime << ", per line(us) = " << (dtime/static_cast<double>(NUM_COLUMNS))*1000000.0 << std::endl; } } BaseClass::updateData(dt); }
int main(int argc, char* argv[]) { bool aflg = false; // All base classes flag bool rflg = false; // Random flag bool sflg = false; // TableStoreage flag bool tflg = false; // Timing flag // default configuration filename const char* configFilename = "test1.edl"; // Parse arguments for (int i = 1; i < argc; i++) { if (std::strcmp(argv[i],"-f") == 0) { configFilename = argv[++i]; } else if (std::strcmp(argv[i],"-a") == 0) { aflg = true; } else if (std::strcmp(argv[i],"-r") == 0) { rflg = true; } else if (std::strcmp(argv[i],"-s") == 0) { sflg = true; } else if (std::strcmp(argv[i],"-t") == 0) { tflg = true; } } // build table const Basic::Table* table = builder(configFilename); // --- // Serialize the table to the output stream // --- if (!tflg) table->serialize(std::cout); // --- // Cast table pointers // --- const Basic::Table1* t1 = dynamic_cast<const Basic::Table1*>(table); const Basic::Table2* t2 = dynamic_cast<const Basic::Table2*>(table); const Basic::Table3* t3 = dynamic_cast<const Basic::Table3*>(table); const Basic::Table4* t4 = dynamic_cast<const Basic::Table4*>(table); // --- // Call the test function for this LFI table type // --- double startTime = getComputerTime(); unsigned int cnt = 0; unsigned int n = 1; if (tflg) n = TIMING_LOOPS; for (unsigned int i = 0; i < n; i++) { if (t1 != nullptr && (aflg || t2 == nullptr) ) { cnt += testIt(t1, tflg, sflg, rflg); } if (t2 != nullptr && (aflg || t3 == nullptr) ) { cnt += testIt(t2, tflg, sflg, rflg); } if (t3 != nullptr && (aflg || t4 == nullptr) ) { cnt += testIt(t3, tflg, sflg, rflg); } if (t4 != nullptr) { cnt += testIt(t4, tflg, sflg, rflg); } } // --- // Timing data // --- if (tflg) { double endTime = Eaagles::getComputerTime(); double deltaTime = endTime - startTime; double perFrameTime = deltaTime/static_cast<double>(TIMING_LOOPS); std::cout << "Total Time = " << deltaTime << " for " << TIMING_LOOPS << " frames." << std::endl; std::cout << "Ave time per frame (uS) = " << perFrameTime*1000000.0 << std::endl; if (cnt > 0) { double perCallTime = deltaTime/static_cast<double>(cnt); std::cout << "Ave time per call (uS) = " << perCallTime*1000000.0 << std::endl; } } return EXIT_SUCCESS; }