my website banner

initial commit
[unix-time-fix] / fixed.c
1 // fixed.c
2 // Proposition for fixing unix time overflow.
3 // copyright 2024, David Polakovic, licensed under GPLv3
4
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10
11 // First four functions are commented more heavily because it
12 // was my first time doing such a thing...
13
14 // Initialize a BigInt from a string
15 typedef struct {
16     int *digits;  // Pointer to an array of digits
17     int size;     // Number of digits
18 } BigInt;
19
20 // Define a structure for a BigInt, which is an integer with arbitrary precision
21 BigInt initBigInt(const char *str) {
22     int len = strlen(str);  // Get the length of the string
23     BigInt num;             // Declare a BigInt variable
24     num.size = len;         // Set the size of BigInt to the length of the string
25     num.digits = (int *)malloc(len * sizeof(int)); // Alloc memory for the digits
26     for (int i = 0; i < len; i++) { // Convert digits to int and store them in reverse
27         num.digits[i] = str[len - 1 - i] - '0'; 
28     }
29     return num;             // Return the initialized BigInt
30 }
31
32 // Free the memory allocated for a BigInt.
33 void freeBigInt(BigInt *num) {
34     free(num->digits);   // Free the memory allocated for digits
35     num->digits = NULL;  // Set the digits pointer to NULL
36     num->size = 0;       // Set the size to 0
37 }
38
39 void printBigInt(BigInt *num) {
40     int leadingZero = 1;   // Flag to handle leading zeros
41     for (int i = num->size - 1; i >= 0; i--) { // Iterate digits in reverse order
42         if (num->digits[i] != 0 || !leadingZero) { // Skip leading zeros
43             printf("%d", num->digits[i]);          // Print the digit
44             leadingZero = 0;                       // Clear the leading zero flag
45         }
46     }
47     if (leadingZero) {
48         printf("0");   // Print 0 if all digits are zero
49     }
50     //printf("\n");
51 }
52
53 int isGreaterOrEqual(BigInt *a, BigInt *b) {
54     if (a->size > b->size) return 1;  // Checks digits count
55     if (a->size < b->size) return 0;
56     for (int i = a->size - 1; i >= 0; i--) { // Compare digits from most significant to least
57         if (a->digits[i] > b->digits[i]) return 1;
58         if (a->digits[i] < b->digits[i]) return 0;
59     }
60     return 1;
61 }
62
63 // NOTE: this function is commented by SkyNet because I got lost in it...
64 void subtractBigInt(BigInt *a, BigInt *b, BigInt *result) {
65     result->size = a->size;  // Set the size of result to the size of a
66     result->digits = (int *)calloc(result->size, sizeof(int));  // Allocate memory and initialize to zero
67     int carry = 0;  // Initialize carry to 0
68     for (int i = 0; i < a->size; i++) {  // Iterate over the digits
69         int digit1 = a->digits[i];  // Get the digit from a
70         int digit2 = (i < b->size) ? b->digits[i] : 0;  // Get the digit from b or 0 if out of range
71         int sub = digit1 - digit2 - carry;  // Perform the subtraction
72         if (sub < 0) {  // Handle borrowing
73             sub += 10;
74             carry = 1;
75         } else {
76             carry = 0;
77         }
78         result->digits[i] = sub;  // Store the result digit
79     }
80     while (result->size > 1 && result->digits[result->size - 1] == 0) {
81         result->size--;  // Remove leading zeros
82     }
83 }
84
85 // The meat
86 void divideBigInt(BigInt *dividend, BigInt *divisor, BigInt *result) {
87     // Initialize result BigInt size and allocate memory for digits
88     result->size = dividend->size; 
89     result->digits = (int *)calloc(result->size, sizeof(int));
90
91     // Initialize current BigInt for intermediate calculations
92     BigInt current;
93     current.size = 0;
94     current.digits = (int *)calloc(dividend->size, sizeof(int));
95
96     // Iterate over each digit of the dividend from the highest to the lowest
97     for (int i = dividend->size - 1; i >= 0; i--) {
98         // Shift digits in the current BigInt to left
99         for (int j = current.size; j > 0; j--) {
100             current.digits[j] = current.digits[j - 1];
101         }
102         // Add the next digit of the dividend to the current BigInt
103         current.digits[0] = dividend->digits[i];
104         current.size++;
105
106         // Remove leading zeros in the current BigInt
107         while (current.size > 1 && current.digits[current.size - 1] == 0) {
108             current.size--;
109         }
110
111         int count = 0;
112         // Perform division if possible
113         while (isGreaterOrEqual(&current, divisor)) {
114             BigInt tempResult;
115             subtractBigInt(&current, divisor, &tempResult);
116             free(current.digits);
117             current = tempResult;
118             count++;
119         }
120         
121         // Store the quotient in the result
122         result->digits[i] = count;
123     }
124
125     // Remove leading zeros in the result
126     while (result->size > 1 && result->digits[result->size - 1] == 0) {
127         result->size--;
128     }
129     
130     free(current.digits);
131 }
132
133
134 // Only to be used in moduloBigInt
135 void multiplyBigInt(BigInt *a, BigInt *b, BigInt *result) {
136     result->size = a->size + b->size;
137     result->digits = (int *)calloc(result->size, sizeof(int));
138
139     for (int i = 0; i < a->size; i++) {
140         int carry = 0;
141         for (int j = 0; j < b->size; j++) {
142             int product = a->digits[i] * b->digits[j] + result->digits[i + j] + carry;
143             result->digits[i + j] = product % 10;
144             carry = product / 10;
145         }
146         result->digits[i + b->size] += carry;
147     }
148
149     while (result->size > 1 && result->digits[result->size - 1] == 0) {
150         result->size--;
151     }
152 }
153
154 // Just for validation...
155 void moduloBigInt(BigInt *dividend, BigInt *divisor, BigInt *result) {
156     BigInt tempDivResult;
157     divideBigInt(dividend, divisor, &tempDivResult);
158
159     BigInt tempMulResult;
160     multiplyBigInt(&tempDivResult, divisor, &tempMulResult);
161
162     subtractBigInt(dividend, &tempMulResult, result);
163
164     freeBigInt(&tempDivResult);
165     freeBigInt(&tempMulResult);
166 }
167
168
169 BigInt loadCurrentUnixTime() {
170     time_t currentTime = time(NULL);
171     char timeStr[20];
172     snprintf(timeStr, sizeof(timeStr), "%ld", currentTime);
173     return initBigInt(timeStr);
174 }
175
176 // Inverse function to substractBigInt
177 void addBigInt(BigInt *a, BigInt *b, BigInt *result) {
178     int maxSize = (a->size > b->size) ? a->size : b->size;
179     result->size = maxSize + 1;  // Extra space for possible carry
180     result->digits = (int *)calloc(result->size, sizeof(int));
181     int carry = 0;
182
183     for (int i = 0; i < maxSize; i++) {
184         int digit1 = (i < a->size) ? a->digits[i] : 0;
185         int digit2 = (i < b->size) ? b->digits[i] : 0;
186         int sum = digit1 + digit2 + carry;
187         result->digits[i] = sum % 10;
188         carry = sum / 10;
189     }
190
191     if (carry > 0) {
192         result->digits[maxSize] = carry;
193     } else {
194         result->size--;
195     }
196 }
197
198 // Just for personal validation...
199 int countDigitsBigInt(BigInt *num) {
200     int count = 0;
201     for (int i = 0; i < num->size; i++) {
202         count++;
203     }
204     return count;
205 }
206
207 int main() {
208   
209     BigInt time_f = loadCurrentUnixTime();
210     BigInt year_s = initBigInt("31536000"); // Seconds in a year
211
212     while (1) {
213       
214         // PRINT:
215         // Current unix time 
216         printf("Unix Time: ");
217         printBigInt(&time_f);
218
219         // Result of modulo time_f % year_s
220         BigInt modResult;
221         moduloBigInt(&time_f, &year_s, &modResult);
222         printf("\tModulo: ");
223         printBigInt(&modResult);
224         
225         // Digit counter of unix time value (only in Integer boundary)
226         int numDigits = countDigitsBigInt(&time_f);
227         printf("\t(%d digits)", numDigits);
228
229         // Year (time_f / year_s) + 1970
230         BigInt yearAddition = initBigInt("1970");
231         BigInt divResult;
232         BigInt finalYear;        
233         divideBigInt(&time_f, &year_s, &divResult);
234         addBigInt(&divResult, &yearAddition, &finalYear);
235         printf("\t\tYear: ");
236         printBigInt(&finalYear);
237         
238         // Nwe line...
239         printf("\n");
240
241         // Increment num1 by 1
242         BigInt one = initBigInt("1");
243         BigInt incrementedTime;
244         addBigInt(&time_f, &one, &incrementedTime);
245
246         freeBigInt(&time_f);
247         time_f = incrementedTime; // Update num1 to the incremented value
248         freeBigInt(&divResult);
249         freeBigInt(&modResult);
250         freeBigInt(&finalYear);
251         freeBigInt(&yearAddition);
252         freeBigInt(&one);
253
254     }
255
256     freeBigInt(&year_s);
257
258     return 0;
259 }
260