void run_all (FILE *fp) { mp_size_t prev_size; int i; TMP_DECL; TMP_MARK; SPEED_TMP_ALLOC_LIMBS (sp.xp_block, SPEED_BLOCK_SIZE, sp.align_xp); SPEED_TMP_ALLOC_LIMBS (sp.yp_block, SPEED_BLOCK_SIZE, sp.align_yp); data_fill (sp.xp_block, SPEED_BLOCK_SIZE); data_fill (sp.yp_block, SPEED_BLOCK_SIZE); for (i = 0; i < size_num; i++) { sp.size = size_array[i].start; prev_size = -1; for (;;) { mp_size_t step; if (option_data == DATA_2FD && sp.size >= 2) sp.xp[sp.size-1] = 2; run_one (fp, &sp, prev_size); prev_size = sp.size; if (option_data == DATA_2FD && sp.size >= 2) sp.xp[sp.size-1] = MP_LIMB_T_MAX; if (option_factor != 0.0) { step = (mp_size_t) (sp.size * option_factor - sp.size); if (step < 1) step = 1; } else if(size_array[i].inc > 0) step = size_array[i].inc; else step = 1; if (step < option_step) step = option_step; sp.size += step; if (sp.size > size_array[i].end) break; } } TMP_FREE; }
// Try allocating two filemaps and try a data_fill that // crosses the boundary between them void test_file_boundary() { const int test_filemap1 = 1; const int test_filemap2 = 2; const int test_clusters = 3; uint32_t clust_nr1 = fat_alloc_filemap(test_filemap1, test_clusters); uint32_t clust_nr2 = fat_alloc_filemap(test_filemap2, test_clusters); // Check that they were allocated next to each other QCOMPARE(clust_nr2, clust_nr1 - test_clusters); fat_finalize(DATA_CLUSTERS); int ret = data_fill(datapage, 4096, clust_nr1 - 1, 512, &filled); QCOMPARE(ret, 0); const uint32_t expected_end = 4096 - 512; const uint32_t expected_offset = (test_clusters - 1) * 4096 + 512; // data_fill is allowed to go past the end of the cluster, // but doesn't have to. QVERIFY(filled >= expected_end); QVERIFY(filled <= 4096); check_fill(datapage, MOCK_FILEMAP_FILL, expected_end, test_filemap2, expected_offset); if (filled > expected_end) { check_fill(datapage + expected_end, MOCK_FILEMAP_FILL, filled - expected_end, test_filemap1, 0); } }
// Try allocating one filemap and check the result void test_one_filemap() { const int test_filemap = 8; const int test_clusters = 17; const uint32_t expected_entry = FAT_ENTRIES - test_clusters; uint32_t clust_nr = fat_alloc_filemap(test_filemap, test_clusters); // Check that filemap was allocated at the end of the image QCOMPARE(clust_nr, expected_entry); fat_finalize(DATA_CLUSTERS); // Check that the last fat page shows the file uint32_t *buf = (uint32_t *) alloc_guarded( (test_clusters + 2) * sizeof(uint32_t)); fat_fill(buf, expected_entry - 1, test_clusters + 2); QCOMPARE(buf[0], (uint32_t) 0); // empty before file // ascending chain except last entry for (uint32_t i = 0; i < test_clusters - 1; i++) { QCOMPARE(buf[i + 1], expected_entry + i + 1); } // end of chain marker QCOMPARE(buf[test_clusters], (uint32_t) 0x0fffffff); // bad cluster marker after file (because it's at the end of // allocatable space) QCOMPARE(buf[test_clusters + 1], (uint32_t) 0x0ffffff7); // Check that an arbitrary cluster can be loaded from the file int ret = data_fill(datapage, 4096, expected_entry + 3, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_FILEMAP_FILL, 4096, test_filemap, 3 * 4096); }
void test_bad_args() { QCOMPARE(fat_extend(0, 1), false); QCOMPARE(fat_extend(FAT_ENTRIES, 1), false); fat_finalize(DATA_CLUSTERS); int ret = data_fill(datapage, 4096, FAT_ENTRIES, 0, &filled); QCOMPARE(ret, EINVAL); }
void test_empty_fat() { // No dirs should be found QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1000), -1); fat_finalize(DATA_CLUSTERS); // required by API fat_fill(fatpage, 0, 1024); // Check the special first two fat entries QCOMPARE(fatpage[0], (uint32_t) 0x0ffffff8); // media byte marker QCOMPARE(fatpage[1], (uint32_t) 0x0fffffff); // end of chain marker VERIFY_ARRAY(fatpage, 2, 1024, (uint32_t) 0); int ret = data_fill(datapage, 4096, 2, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); VERIFY_ARRAY(datapage, 0, 4096, (char) 0); }
// Try allocating one directory and check the result void test_one_dir() { const int test_dir_index = 5; uint32_t clust_nr = fat_alloc_dir(test_dir_index); QCOMPARE(clust_nr, (uint32_t) 2); QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index); QCOMPARE(fat_dir_index(3), -1); QCOMPARE(fat_dir_index(4), -1); fat_finalize(DATA_CLUSTERS); // Check that fat_finalize didn't mess up the entries QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index); QCOMPARE(fat_dir_index(3), -1); QCOMPARE(fat_dir_index(4), -1); // Check that the first fat page shows the directory fat_fill(fatpage, 0, 1024); // Check the special first two fat entries QCOMPARE(fatpage[0], (uint32_t) 0x0ffffff8); // media byte marker QCOMPARE(fatpage[1], (uint32_t) 0x0fffffff); // end of chain marker // Check the new directory entry QCOMPARE(fatpage[2], (uint32_t) 0x0fffffff); // end of chain marker VERIFY_ARRAY(fatpage, 3, 1024, (uint32_t) 0); // everything else 0 // Check that data_fill accesses the directory int ret = data_fill(datapage, 8192, 2, 0, &filled); QCOMPARE(ret, 0); // Check that the whole directory cluster was filled QVERIFY2(filled >= 4096, QTest::toString(filled)); // Check that dir_fill did the filling check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index, 0); // and any extra fill is from an empty cluster // (current code does not fill more than the dir but it's allowed to) VERIFY_ARRAY(datapage, 4096, (int) filled, (char) 0); }
void run_one (FILE *fp, struct speed_params *s, mp_size_t prev_size) { const char *first_open_fastest, *first_open_notfastest, *first_close; int j,i, fastest, want_data; double fastest_time; TMP_DECL; TMP_MARK; /* allocate data, unless all routines are NODATA */ want_data = 0; for (i = 0; i < num_choices; i++) want_data |= ((choice[i].p->flag & FLAG_NODATA) == 0); if (want_data) { SPEED_TMP_ALLOC_LIMBS (sp.xp, s->size, s->align_xp); SPEED_TMP_ALLOC_LIMBS (sp.yp, s->size, s->align_yp); data_fill (s->xp, s->size); data_fill (s->yp, s->size); } else { sp.xp = NULL; sp.yp = NULL; } if (prev_size == -1 && option_cmp == CMP_DIFFPREV) { first_open_fastest = "(#"; first_open_notfastest = " ("; first_close = ")"; } else { first_open_fastest = "#"; first_open_notfastest = " "; first_close = ""; } fastest = -1; fastest_time = -1.0; for (i = 0; i < num_choices; i++) { if( choice[i].nsum!=0)continue; s->r = choice[i].r; if( choice[i].colfile==-1) {choice[i].time = speed_measure (choice[i].p->fun, s);} else {FILE *fp;char buf[1024],buf2[1024],*p;int got=0; choice[i].time=-1.0; fp=fopen(choice[i].filename,"rt"); if(fp==0){printf("Cant open %s\n",choice[i].filename);exit(1);} while(fgets(buf,1024,fp)!=0) if(atoi(buf)==s->size) {p=buf; for(j=0;j<=choice[i].colfile;j++) {if(sscanf(p," %s",buf2)!=1)break; p=strstr(p,buf2)+strlen(buf2);} if(j==choice[i].colfile+1) {while((p=strstr(buf2,"#"))!=0)*p=' ';// exclude # choice[i].time=atof(buf2); } break;} fclose(fp); } choice[i].no_time = (choice[i].time == -1.0); if (! choice[i].no_time) choice[i].time *= choice[i].scale; /* Apply the effect of CMP_DIFFPREV, but the new choice[i].prev_time is before any differences. */ if(choice[i].colfile==-1) { double t; t = choice[i].time; if (t != -1.0 && option_cmp == CMP_DIFFPREV && prev_size != -1) { if (choice[i].prev_time == -1.0) choice[i].no_time = 1; else choice[i].time = choice[i].time - choice[i].prev_time; } choice[i].prev_time = t; } } for (i = 0; i < num_choices; i++) {if(choice[i].nsum==0)continue; choice[i].time=0;choice[i].no_time=0; for(j=0;j<choice[i].nsum;j++) {choice[i].time+=choice[choice[i].sum[j]].time; if(choice[choice[i].sum[j]].no_time)choice[i].no_time=1; } } for (i = 0; i < num_choices; i++) { if (choice[i].no_time || choice[i].colfile!=-1) continue; if (option_cmp == CMP_DIFFPREV) { /* Conversion for UNIT_CYCLESPERLIMB differs in CMP_DIFFPREV. */ if (option_unit == UNIT_CYCLES) choice[i].time /= speed_cycletime; else if (option_unit == UNIT_CYCLESPERLIMB) { if (prev_size == -1) choice[i].time /= speed_cycletime; else choice[i].time /= (speed_cycletime * (SIZE_TO_DIVISOR(s->size) - SIZE_TO_DIVISOR(prev_size))); } } else { if (option_unit == UNIT_CYCLES) choice[i].time /= speed_cycletime; else if (option_unit == UNIT_CYCLESPERLIMB) choice[i].time /= (speed_cycletime * SIZE_TO_DIVISOR(s->size)); } } for (i = 0; i < num_choices; i++) { if (choice[i].no_time) continue; /* Look for the fastest after CMP_DIFFPREV has been applied, but before CMP_RATIO or CMP_DIFFERENCE. There's only a fastest shown if there's more than one routine. */ for(j=0;j<xcoln;j++)if(xcol[j]==i)break; // excluded from fastest choice if (j==xcoln && num_choices > 1 && (fastest == -1 || choice[i].time < fastest_time)) { fastest = i; fastest_time = choice[i].time; } } for (i = 0; i < num_choices; i++) { if (choice[i].no_time ) continue; if (option_cmp != CMP_DIFFPREV) { if (option_cmp == CMP_RATIO && i != option_cmp_pos) { /* A ratio isn't affected by the units chosen. */ if (choice[option_cmp_pos].no_time || choice[option_cmp_pos].time == 0.0) choice[i].no_time = 1; else choice[i].time /= choice[option_cmp_pos].time; } else if (option_cmp == CMP_DIFFERENCE && i != option_cmp_pos) { if (choice[option_cmp_pos].no_time) { choice[i].no_time = 1; continue; } choice[i].time -= choice[option_cmp_pos].time; } } } if (option_gnuplot) { /* In CMP_DIFFPREV, don't print anything for the first size, start with the second where an actual difference is available. In CMP_RATIO, print the "first" ie option_cmp_pos column as 1.0. The 9 decimals printed is much more than the expected precision of the measurements actually. */ if (! (option_cmp == CMP_DIFFPREV && prev_size == -1)) { fprintf (fp, "%-6ld ", s->size); for (i = 0; i < num_choices; i++) fprintf (fp, " %.9e", choice[i].no_time ? 0.0 : (option_cmp == CMP_RATIO && i == option_cmp_pos) ? 1.0 : choice[i].time); fprintf (fp, "\n"); } } else { fprintf (fp, "%-6ld ", s->size); for (i = 0; i < num_choices; i++) { char buf[128]; int decimals; if (choice[i].no_time) { fprintf (fp, " %*s", COLUMN_WIDTH, "n/a"); } else {if (option_unit == UNIT_CYCLESPERLIMB || (option_cmp == CMP_RATIO && i != option_cmp_pos)) decimals = 4; else if (option_unit == UNIT_CYCLES) decimals = 2; else decimals = 9; sprintf (buf, "%s%.*f%s", i == fastest ? first_open_fastest : first_open_notfastest, decimals, choice[i].time, first_close); fprintf (fp, " %*s", COLUMN_WIDTH, buf); } } fprintf (fp, "\n"); } TMP_FREE; }
void run_one (FILE *fp, struct speed_params *s, mp_size_t prev_size) { const char *first_open_fastest, *first_open_notfastest, *first_close; int i, fastest, want_data; double fastest_time; TMP_DECL; TMP_MARK; /* allocate data, unless all routines are NODATA */ want_data = 0; for (i = 0; i < num_choices; i++) want_data |= ((choice[i].p->flag & FLAG_NODATA) == 0); if (want_data) { SPEED_TMP_ALLOC_LIMBS (sp.xp, s->size, s->align_xp); SPEED_TMP_ALLOC_LIMBS (sp.yp, s->size, s->align_yp); data_fill (s->xp, s->size); data_fill (s->yp, s->size); } else { sp.xp = NULL; sp.yp = NULL; } if (prev_size == -1 && option_cmp == CMP_DIFFPREV) { first_open_fastest = "(#"; first_open_notfastest = " ("; first_close = ")"; } else { first_open_fastest = "#"; first_open_notfastest = " "; first_close = ""; } fastest = -1; fastest_time = -1.0; for (i = 0; i < num_choices; i++) { s->r = choice[i].r; choice[i].time = speed_measure (choice[i].p->fun, s); choice[i].no_time = (choice[i].time == -1.0); if (! choice[i].no_time) choice[i].time *= choice[i].scale; /* Apply the effect of CMP_DIFFPREV, but the new choice[i].prev_time is before any differences. */ { double t; t = choice[i].time; if (t != -1.0 && option_cmp == CMP_DIFFPREV && prev_size != -1) { if (choice[i].prev_time == -1.0) choice[i].no_time = 1; else choice[i].time = choice[i].time - choice[i].prev_time; } choice[i].prev_time = t; } if (choice[i].no_time) continue; /* Look for the fastest after CMP_DIFFPREV has been applied, but before CMP_RATIO or CMP_DIFFERENCE. There's only a fastest shown if there's more than one routine. */ if (num_choices > 1 && (fastest == -1 || choice[i].time < fastest_time)) { fastest = i; fastest_time = choice[i].time; } if (option_cmp == CMP_DIFFPREV) { /* Conversion for UNIT_CYCLESPERLIMB differs in CMP_DIFFPREV. */ if (option_unit == UNIT_CYCLES) choice[i].time /= speed_cycletime; else if (option_unit == UNIT_CYCLESPERLIMB) { if (prev_size == -1) choice[i].time /= speed_cycletime; else choice[i].time /= (speed_cycletime * (SIZE_TO_DIVISOR(s->size) - SIZE_TO_DIVISOR(prev_size))); } } else { if (option_unit == UNIT_CYCLES) choice[i].time /= speed_cycletime; else if (option_unit == UNIT_CYCLESPERLIMB) choice[i].time /= (speed_cycletime * SIZE_TO_DIVISOR(s->size)); if (option_cmp == CMP_RATIO && i > 0) { /* A ratio isn't affected by the units chosen. */ if (choice[0].no_time || choice[0].time == 0.0) choice[i].no_time = 1; else choice[i].time /= choice[0].time; } else if (option_cmp == CMP_DIFFERENCE && i > 0) { if (choice[0].no_time) { choice[i].no_time = 1; continue; } choice[i].time -= choice[0].time; } } } if (option_gnuplot) { /* In CMP_DIFFPREV, don't print anything for the first size, start with the second where an actual difference is available. In CMP_RATIO, print the first column as 1.0. The 9 decimals printed is much more than the expected precision of the measurements actually. */ if (! (option_cmp == CMP_DIFFPREV && prev_size == -1)) { fprintf (fp, "%-6ld ", s->size); for (i = 0; i < num_choices; i++) fprintf (fp, " %.9e", choice[i].no_time ? 0.0 : (option_cmp == CMP_RATIO && i == 0) ? 1.0 : choice[i].time); fprintf (fp, "\n"); } } else { fprintf (fp, "%-6ld ", s->size); for (i = 0; i < num_choices; i++) { char buf[128]; int decimals; if (choice[i].no_time) { fprintf (fp, " %*s", COLUMN_WIDTH, "n/a"); } else {if (option_unit == UNIT_CYCLESPERLIMB || (option_cmp == CMP_RATIO && i > 0)) decimals = 4; else if (option_unit == UNIT_CYCLES) decimals = 2; else decimals = 9; sprintf (buf, "%s%.*f%s", i == fastest ? first_open_fastest : first_open_notfastest, decimals, choice[i].time, first_close); fprintf (fp, " %*s", COLUMN_WIDTH, buf); } } fprintf (fp, "\n"); } TMP_FREE; }
// Try allocating two directories and then extending the first twice void test_extend_dir_twice() { const int test_dir_index1 = 7; const int test_dir_index2 = 11; uint32_t clust_nr1 = fat_alloc_dir(test_dir_index1); uint32_t clust_nr2 = fat_alloc_dir(test_dir_index2); QCOMPARE(clust_nr1, (uint32_t) 2); QCOMPARE(clust_nr2, (uint32_t) 3); bool ret1 = fat_extend(clust_nr1, 1); QCOMPARE(ret1, true); bool ret2 = fat_extend(clust_nr1, 1); QCOMPARE(ret2, true); QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index1); QCOMPARE(fat_dir_index(3), test_dir_index2); QCOMPARE(fat_dir_index(4), test_dir_index1); QCOMPARE(fat_dir_index(5), test_dir_index1); QCOMPARE(fat_dir_index(6), -1); fat_finalize(DATA_CLUSTERS); QCOMPARE(fat_dir_index(0), -1); QCOMPARE(fat_dir_index(1), -1); QCOMPARE(fat_dir_index(2), test_dir_index1); QCOMPARE(fat_dir_index(3), test_dir_index2); QCOMPARE(fat_dir_index(4), test_dir_index1); QCOMPARE(fat_dir_index(5), test_dir_index1); QCOMPARE(fat_dir_index(6), -1); // Check the first fat page fat_fill(fatpage, 0, 1024); QCOMPARE(fatpage[0], (uint32_t) 0x0ffffff8); // media byte marker QCOMPARE(fatpage[1], (uint32_t) 0x0fffffff); // end of chain marker QCOMPARE(fatpage[2], (uint32_t) 4); // next cluster of dir 1 QCOMPARE(fatpage[3], (uint32_t) 0x0fffffff); // end of chain marker QCOMPARE(fatpage[4], (uint32_t) 5); // next cluster of dir 1 QCOMPARE(fatpage[5], (uint32_t) 0x0fffffff); // end of chain marker VERIFY_ARRAY(fatpage, 6, 1024, (uint32_t) 0); // everything else 0 // Check that data_fill gets it right int ret = data_fill(datapage, 4096, 2, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index1, 0); ret = data_fill(datapage, 4096, 3, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index2, 0); ret = data_fill(datapage, 4096, 4, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index1, 4096); ret = data_fill(datapage, 4096, 5, 0, &filled); QCOMPARE(ret, 0); QCOMPARE(filled, (uint32_t) 4096); check_fill(datapage, MOCK_DIR_FILL, 4096, test_dir_index1, 2 * 4096); }