// Immortal Number Search // by Daniel Marschall // FUT TODO: Auch "r%10" und die letzte Ziffer übereinstimmen? + weitere konsistenzprüfungen #include #include #include #include #include #include static inline char* getTimeStamp(char *timestamp_buf, const int len) { time_t now = time(0); strftime (timestamp_buf, len, "%a, %d %b %Y %T %z", localtime(&now)); return timestamp_buf; } // ACHTUNG: BEI GROSSEN ZAHLEN GIBTS KERNEL PANIC, LOL (Speicher knapp) static inline bool isImmortal(const mpz_t n, const unsigned int m) { // unsigned int m = strlen(n); mpz_t rop; mpz_init(rop); mpz_t m_pow; mpz_init(m_pow); mpz_ui_pow_ui(m_pow, 10, m); mpz_powm_ui(rop, n, 2, m_pow); // rop = n^2 % (mod 10^m) bool res = mpz_cmp(rop, n) == 0; mpz_clear(m_pow); mpz_clear(rop); return res; } static inline void mygetline(char* line, size_t size, FILE* myfile) { if (fgets(line, size, myfile) == NULL) { line = ""; return; } size_t ln = strlen(line) - 1; if (line[ln] == '\n') line[ln] = '\0'; ln = strlen(line) - 1; if (line[ln] == '\r') line[ln] = '\0'; return; } int main(int argc, char** argv) { const char* SIGNATURE = "Immortal Number Report File Version 3.00"; const char* END_SIG = "END OF REPORT"; if (argc != 2) { fprintf(stderr, "Syntax: %s \n", argv[0]); return 2; } const char* DATA_FILENAME = argv[1]; unsigned char* a; unsigned /* long long */ int a_size = -1; unsigned /* long long */ int top = -1; char debug_timestamp[255]; getTimeStamp(debug_timestamp, 255); printf("%s - Immort-Testprogramm gestartet\n", debug_timestamp); char line[255]; FILE* myfile = fopen(DATA_FILENAME, "r"); if (!myfile) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - File not found: %s", debug_timestamp, DATA_FILENAME); return EXIT_FAILURE; } // __try { mygetline(line, sizeof line, myfile); // Major. signature if (strcmp(line, SIGNATURE) != 0 /* not equal */) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - Load error: Wrong format signature. Expecting '%s' but is '%s'.\n", debug_timestamp, SIGNATURE, line); fclose(myfile); return EXIT_FAILURE; } mygetline(line, sizeof line, myfile); // Minor. signature mygetline(line, sizeof line, myfile); // "" mygetline(line, sizeof line, myfile); // "(Starting time)" mygetline(line, sizeof line, myfile); // Starting time mygetline(line, sizeof line, myfile); // "" mygetline(line, sizeof line, myfile); // "(Save timestamp)" mygetline(line, sizeof line, myfile); // Timestamp mygetline(line, sizeof line, myfile); // "" mygetline(line, sizeof line, myfile); // "(Base)" mygetline(line, sizeof line, myfile); // 10 unsigned int base = atoi(line); if (base != 10) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - This edition can only work with base = 10.\n", debug_timestamp); fclose(myfile); return EXIT_FAILURE; } mygetline(line, sizeof line, myfile); // "" mygetline(line, sizeof line, myfile); // "(Root)" mygetline(line, sizeof line, myfile); // 5 unsigned int root = atoi(line); if (root != 5) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - This edition can only work with root = 5.\n", debug_timestamp); fclose(myfile); return EXIT_FAILURE; } mygetline(line, sizeof line, myfile); // "" mygetline(line, sizeof line, myfile); // "(Digits)" mygetline(line, sizeof line, myfile); // C unsigned /* long long */ int u = atoi(line) - 1; mygetline(line, sizeof line, myfile); // "" mygetline(line, sizeof line, myfile); // "(r)" mygetline(line, sizeof line, myfile); // r mygetline(line, sizeof line, myfile); // "" a_size = u + 1; getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - Count: %d\n", debug_timestamp, a_size); // a = new unsigned char[a_size]; a = (unsigned char*) malloc(a_size * sizeof(unsigned char)); if (a == NULL) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - Memory allocation failed!\n", debug_timestamp); return EXIT_FAILURE; } mygetline(line, sizeof line, myfile); // "(Reversed notation)" do { mygetline(line, sizeof line, myfile); for (unsigned int i = 0; i < strlen(line); ++i) { if (++top >= a_size) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - Corrupt: Formal and actual length mismatch! (Overflow)\n", debug_timestamp); return EXIT_FAILURE; } char toadd = line[i] - '0'; a[top] = toadd; } } while (strcmp(line, "") != 0 /* not equal */); if (top+1 != a_size) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - Corrupt: Formal and actual length mismatch! (Underflow)\n", debug_timestamp); return EXIT_FAILURE; } mygetline(line, sizeof line, myfile); if (strcmp(line, END_SIG) != 0 /* not equal */) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - Corrupt: End-signature mismatch.\n", debug_timestamp); return EXIT_FAILURE; } // } __finally { fclose(myfile); // } getTimeStamp(debug_timestamp, 255); printf("%s - Beginne Immort-Test...\n", debug_timestamp); mpz_t num; mpz_init(num); mpz_t m_pow; mpz_init(m_pow); mpz_t ra; mpz_init(ra); for (unsigned int i = 0; i < top + 1 /* a.count() */; ++i) { unsigned char xa = a[i]; if (i > 0) { xa = 9 - xa; } else { xa = 11 - xa; } mpz_ui_pow_ui(m_pow, 10, i); mpz_mul_ui(ra, m_pow, xa); mpz_add(num, num, ra); } mpz_clear(ra); mpz_clear(m_pow); if (!isImmortal(num, top + 1)) { getTimeStamp(debug_timestamp, 255); fprintf(stderr, "%s - Integrity test failed. Is not immortal.\n", debug_timestamp); mpz_clear(num); return EXIT_FAILURE; } mpz_clear(num); getTimeStamp(debug_timestamp, 255); printf("%s - Immort test succeed.\n", debug_timestamp); return EXIT_SUCCESS; }