0% found this document useful (0 votes)
4 views

Lab_Report

The document outlines the design and implementation of various finite automata (DFA and NFA) and grammar transformations in C programming. It includes specifications for accepting binary strings, valid C variable names, Gmail IDs, NTC numbers, and handling left recursion in grammars. Each section provides theoretical background, state design, and corresponding C code for validation and output.

Uploaded by

ThundeR
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Lab_Report

The document outlines the design and implementation of various finite automata (DFA and NFA) and grammar transformations in C programming. It includes specifications for accepting binary strings, valid C variable names, Gmail IDs, NTC numbers, and handling left recursion in grammars. Each section provides theoretical background, state design, and corresponding C code for validation and output.

Uploaded by

ThundeR
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 32

Sanjeet Mijar Symbol No.

: 28108/078
1. Design a DFA to simulate the following machines
a. Accepting binary string that start with 0 and ends with 1.

Theory:
A Deterministic Finite Automaton (DFA) for this language needs to:

1. Start in initial state q0

2. Transition to accepting state q1 on input '0'

3. Stay in q1 on subsequent '0's

4. Move to accepting state q2 on '1' in q1

5. Loop in q2 on '1's

6. Return to q1 on '0' in q2

7. Reject any string starting with '1' (transition to dead state q3)

States:

 q0: initial state

 q1: first symbol was '0'

 q2: last symbol was '1' (accepting state)

 q3: dead state (reject)

Program:
#include <stdio.h>
#include <string.h>

int isValidBinaryString(char str[]) {


int len = strlen(str);
// Check if string is empty or contains non-binary characters
if (len == 0)
return 0;

for (int i = 0; i < len; i++) {


Sanjeet Mijar Symbol No.: 28108/078
if (str[i] != '0' && str[i] != '1') {
return 0;
}
}
// Check if it starts with 0 and ends with 1
if (str[0] == '0' && str[len - 1] == '1') {
return 1;
} else {
return 0;
}
}

int main() {
char input[100];

printf("Enter a binary string: ");


scanf("%s", input);
if (isValidBinaryString(input)) {
printf("Valid binary string: It starts with 0 and ends with 1.\n");
} else {
printf("Invalid binary string: It does not start with 0 and end with 1.\n");
}

// Required Output
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}
Output:
Sanjeet Mijar Symbol No.: 28108/078

b. Accepting the valid variable names in C program

Theory:
C variable names must:

1. Begin with letter or underscore

2. Contain only letters, digits, or underscores

3. Not be a keyword (though DFA can't check this)

DFA Design:

 q0: initial state

 q1: first character was valid (letter/underscore) - accepting

 q2: subsequent characters valid (letters/digits/underscores) - accepting

 q3: invalid character encountered - dead state

Program:
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int isKeyword(const char *str) {


const char *keywords[] = {
"auto", "break", "case", "char", "const", "continue", "default",
"do", "double", "else", "enum", "extern", "float", "for", "goto",
Sanjeet Mijar Symbol No.: 28108/078
"if", "int", "long", "register", "return", "short", "signed",
"sizeof", "static", "struct", "switch", "typedef", "union",
"unsigned", "void", "volatile", "while", "inline", "restrict", "_Bool",
"_Complex", "_Imaginary"
};
int n = sizeof(keywords) / sizeof(keywords[0]);
for (int i = 0; i < n; i++) {
if (strcmp(str, keywords[i]) == 0) {
return 1;
}
}
return 0;
}

int isValidVariableName(char str[]) {


int i, len = strlen(str);
// Empty string not allowed
if (len == 0)
return 0; // First character must be a letter or underscore
if (!isalpha(str[0]) && str[0] != '_')
return 0;
// Check rest of the characters
for (i = 1; i < len; i++) {
if (!isalnum(str[i]) && str[i] != '_')
return 0;
}
// Check if it's a keyword
if (isKeyword(str))
return 0;
return 1;
}

int main() {
char input[100];

printf("Enter a string to check as C variable name: ");


scanf("%s", input);

if (isValidVariableName(input)) {
printf("Valid C variable name.\n");
} else {
printf("Invalid C variable name.\n");
}
// Required Output
Sanjeet Mijar Symbol No.: 28108/078
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}

c. Accepting the valid gmail ID

Theory:
Valid Gmail ID format:

1. Local part (before @) must be 6-30 characters

2. Can contain letters, numbers, dots (but not consecutive dots)

3. Must contain exactly one @ symbol

4. Must end with "@gmail.com"


Sanjeet Mijar Symbol No.: 28108/078
DFA Design:
This requires multiple states to:

1. Count characters (6-30)

2. Validate character types

3. Check for single @

4. Verify exact "gmail.com" suffix

Program:
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int isValidGmail(char email[]) {


int len = strlen(email);
// Check if email ends with @gmail.com
if (len < 11 || strcmp(&email[len - 10], "@gmail.com") != 0)
return 0;// Check the local part before @
for (int i = 0; i < len - 10; i++) {
char ch = email[i];
if (i == 0 && !isalpha(ch))
return 0;
if (!isalnum(ch) && ch != '.')
return 0;
}
return 1;
}

int main() {
char input[100];
printf("Enter a Gmail ID: ");
scanf("%s", input);

if (isValidGmail(input)) {
printf("Valid Gmail ID.\n");
} else {
printf("Invalid Gmail ID.\n");
}
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");
Sanjeet Mijar Symbol No.: 28108/078
return 0;
}
Output:

d. Accepting the prepaid NTC number

Theory:
NTC (Nepal Telecom) prepaid numbers typically:

1. Start with 98 or 97
2. Are 10 digits total
3. Follow specific numbering patterns

DFA Design:

 States to:

1. Verify first digit is 9


2. Verify second digit is 7 or 8
3. Count remaining 8 digits
4. Reject if pattern or length invalid
Sanjeet Mijar Symbol No.: 28108/078
Program:
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int isValidNTCPrepaid(char number[]) {


int len = strlen(number);
// Must be 10 digits
if (len != 10)
return 0;
// Must contain only digits
for (int i = 0; i < len; i++) {
if (!isdigit(number[i]))
return 0;
}
// Check valid NTC prepaid prefixes
if ((strncmp(number, "984", 3) == 0) ||
(strncmp(number, "985", 3) == 0) ||
(strncmp(number, "986", 3) == 0)) {
return 1;
}
return 0;
}

int main() {
char input[20];

printf("Enter a NTC prepaid number: ");


scanf("%s", input);

if (isValidNTCPrepaid(input)) {
printf("Valid NTC prepaid number.\n");
} else {
printf("Invalid NTC prepaid number.\n");
}
// Required Output
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}
Output:
Sanjeet Mijar Symbol No.: 28108/078
Sanjeet Mijar Symbol No.: 28108/078

LAB 2. Design a NFA to simulate the following machine


a. Accepting RE (a + b)*a over  = {a,b}

Theory:
The NFA needs to:

1. Accept any string ending with 'a'


2. Allow any combination of 'a's and 'b's before the final 'a'

NFA Design:

 q0: initial state


 q1: accepting state
 Transitions:

o q0 to q0 on a
o q0 to q0 on b
o q0 to q1 on a

Program:
#include <stdio.h>
#include <string.h>

// Function to check if the string is accepted by NFA for (a + b)*a


int isAcceptedByNFA(char str[]) {
int len = strlen(str);

if (len == 0)
return 0; // Empty string not accepted
Sanjeet Mijar Symbol No.: 28108/078

// Check if last character is 'a'


if (str[len - 1] == 'a') {
// Also check if all characters are either a or b
for (int i = 0; i < len; i++) {
if (str[i] != 'a' && str[i] != 'b') {
return 0;
}
}
return 1; // Valid string ending in 'a'
}

return 0;
}

int main() {
char input[100];

printf("Enter a string over S = {a, b}: ");


scanf("%s", input);

if (isAcceptedByNFA(input)) {
printf("String is ACCEPTED by the NFA for (a + b)*a\n");
} else {
printf("String is REJECTED by the NFA for (a + b)*a\n");
}

// Required Output
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}
Output:
Sanjeet Mijar Symbol No.: 28108/078

b. Accepting RE (a+b)(a+b) over  = {a,b}

Theory:
This accepts exactly two symbols where each can be 'a' or 'b'

NFA Design:

 q0: initial state


 q1: after first symbol
 q2: accepting state after second symbol
 Transitions from q0 to q1 on a/b
 Transitions from q1 to q2 on a/b

Program:
#include <stdio.h>
#include <string.h>

// Function to check if string is accepted by NFA for (a + b)(a + b)


Sanjeet Mijar Symbol No.: 28108/078
int isAcceptedByNFA(char str[]) {
int len = strlen(str);

// String must be exactly 2 characters long


if (len != 2)
return 0;

// Check if both characters are either 'a' or 'b'


if ((str[0] == 'a' || str[0] == 'b') &&
(str[1] == 'a' || str[1] == 'b')) {
return 1;
}

return 0;
}

int main() {
char input[100];

printf("Enter a string over S = {a, b}: ");


scanf("%s", input);

if (isAcceptedByNFA(input)) {
printf("String is ACCEPTED by the NFA for (a + b)(a + b)\n");
} else {
printf("String is REJECTED by the NFA for (a + b)(a + b)\n");
}

// Required Output
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}
Output:
Sanjeet Mijar Symbol No.: 28108/078

LAB 3. Write a program to remove left recursion from the following grammar
a. S  Sab | ab | a | b (Grammar 1)

Theory:
Left recursion occurs when a non-terminal appears as the first symbol on the right-hand
side of its own production.

Steps:

1. Identify left-recursive productions (S → Sab)


2. Apply standard elimination:
Sanjeet Mijar Symbol No.: 28108/078
o S → abS' | aS' | bS'
o S' → abS' | ε

Program:
#include <stdio.h>
#include <string.h>

// Structure to store grammar rules


struct Grammar {
char nonTerminal;
char productions[10][20];
int productionCount;
};

// Function to check if a production is left-recursive


int isLeftRecursive(char nonTerminal, char production[]) {
return production[0] == nonTerminal;
}

int main() {
struct Grammar G;
G.nonTerminal = 'S';
G.productionCount = 4;

// Original grammar: S ? Sab | ab | a | b


strcpy(G.productions[0], "Sab");
strcpy(G.productions[1], "ab");
strcpy(G.productions[2], "a");
strcpy(G.productions[3], "b");

char alpha[10][20], beta[10][20]; // alpha for left recursion, beta for non-recursive
int alphaCount = 0, betaCount = 0;

// Classify productions
for (int i = 0; i < G.productionCount; i++) {
if (isLeftRecursive(G.nonTerminal, G.productions[i])) {
strcpy(alpha[alphaCount++], G.productions[i] + 1); // remove the non-terminal itself
} else {
strcpy(beta[betaCount++], G.productions[i]);
}
}

// Output the new grammar


printf("Grammar after removing left recursion:\n");
Sanjeet Mijar Symbol No.: 28108/078

// First production line: S ? ßA'


printf("%c ? ", G.nonTerminal);
for (int i = 0; i < betaCount; i++) {
printf("%s%c'", beta[i], G.nonTerminal);
if (i != betaCount - 1)
printf(" | ");
}
printf("\n");

// Second production line: S' ? aA' | e


printf("%c' ? ", G.nonTerminal);
if (alphaCount == 0) {
printf("e");
} else {
for (int i = 0; i < alphaCount; i++) {
printf("%s%c'", alpha[i], G.nonTerminal);
if (i != alphaCount - 1)
printf(" | ");
}
printf(" | e");
}
printf("\n");

// Required Output
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}
Output:
Sanjeet Mijar Symbol No.: 28108/078

b. A  A0 | A1 | 0 (Grammar 2)

Steps:

1. Left-recursive productions: A → A0, A → A1


2. Eliminate to:

o A → 0A'
o A' → 0A' | 1A' | ε

Program:
#include <stdio.h>
#include <string.h>

// Structure to store grammar rules


struct Grammar {
char nonTerminal;
char productions[10][20];
int productionCount;
};

// Function to check if a production is left-recursive


int isLeftRecursive(char nonTerminal, char production[]) {
return production[0] == nonTerminal;
}

int main() {
struct Grammar G;
G.nonTerminal = 'A';
G.productionCount = 3;

// Original grammar: A ? A0 | A1 | 0
strcpy(G.productions[0], "A0");
strcpy(G.productions[1], "A1");
strcpy(G.productions[2], "0");

char alpha[10][20], beta[10][20]; // alpha for left recursion, beta for non-recursive
int alphaCount = 0, betaCount = 0;

// Classify productions
for (int i = 0; i < G.productionCount; i++) {
if (isLeftRecursive(G.nonTerminal, G.productions[i])) {
strcpy(alpha[alphaCount++], G.productions[i] + 1); // remove the non-terminal itself
Sanjeet Mijar Symbol No.: 28108/078
} else {
strcpy(beta[betaCount++], G.productions[i]);
}
}

// Output the new grammar


printf("Grammar after removing left recursion:\n");

// First production line: A ? ßA'


printf("%c ? ", G.nonTerminal);
for (int i = 0; i < betaCount; i++) {
printf("%s%c'", beta[i], G.nonTerminal);
if (i != betaCount - 1)
printf(" | ");
}
printf("\n");

// Second production line: A' ? aA' | e


printf("%c' ? ", G.nonTerminal);
if (alphaCount == 0) {
printf("e");
} else {
for (int i = 0; i < alphaCount; i++) {
printf("%s%c'", alpha[i], G.nonTerminal);
if (i != alphaCount - 1)
printf(" | ");
}
printf(" | e");
}
printf("\n");

// Required Output
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}
Output:
Sanjeet Mijar Symbol No.: 28108/078

LAB 4. Write a program to create a symbol table for the variables (for data types
only)

Theory:
A symbol table stores:

1. Variable names
Sanjeet Mijar Symbol No.: 28108/078
2. Data types
3. Values
4. Memory addresses

Implementation Approach:

1. Parse input declarations


2. Extract variable name, type, value
3. Assign memory addresses (sequential or based on type size)
4. Store in a data structure (hash table, array, etc.)

Example Processing:
Input: "int a = 2, float b = 3.5"
Output:

Variable Valu Addre


Type
Name e ss

a integer 2 100

real
b 3.5 200
number

Program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Symbol {
char varName[20];
char type[20];
char value[20];
int address;
};

int main() {
char input[200];
struct Symbol table[20];
int count = 0;
int address = 100;

printf("Enter the variable declaration line (e.g., int a=2, float b=3.5):\n");
Sanjeet Mijar Symbol No.: 28108/078
fgets(input, sizeof(input), stdin);

char *token = strtok(input, ",");


while (token != NULL) {
char dataType[20], var[20], val[20];
int i = 0;

// Skip leading spaces


while (token[i] == ' ') i++;

// Read the data type


sscanf(token + i, "%s", dataType);

// Move past data type


char *equalPos = strchr(token, '=');
if (equalPos != NULL) {
// Find variable name and value
int varLength = equalPos - token;
sscanf(token + i + strlen(dataType), "%s", var);
sscanf(equalPos + 1, "%s", val);

// Remove potential trailing characters


var[strcspn(var, " =;\n")] = '\0';
val[strcspn(val, " ;\n")] = '\0';

// Fill in symbol table


strcpy(table[count].varName, var);
if (strcmp(dataType, "int") == 0)
strcpy(table[count].type, "integer");
else if (strcmp(dataType, "float") == 0)
strcpy(table[count].type, "real number");
else
strcpy(table[count].type, dataType); // Default

strcpy(table[count].value, val);
table[count].address = address;
address += 100;
count++;
}

token = strtok(NULL, ",");


}

// Display Symbol Table


Sanjeet Mijar Symbol No.: 28108/078
printf("\n%-15s %-15s %-10s %-10s\n", "Variable Name", "Type", "Value", "Address");
for (int i = 0; i < count; i++) {
printf("%-15s %-15s %-10s %-10d\n", table[i].varName, table[i].type, table[i].value, table[i].address);
}
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");

return 0;
}
Output:

LAB 5. Write a program to find set of non-terminals, set of terminals, set of


productions and starting symbol. Here you have to take the CFG as input in
file. Theory:
For a given CFG, identify:
Sanjeet Mijar Symbol No.: 28108/078
1. Non-terminals (uppercase/lhs of productions)
2. Terminals (alphabet symbols)
3. Productions (rules)
4. Start symbol (usually first non-terminal)

Implementation Steps:

1. Read grammar from file


2. Parse each production
3. Extract non-terminals from LHS
4. Extract terminals from RHS (excluding non-terminals)
5. Collect all productions
6. Identify start symbol

Example (3a):
Input: S → Sab | ab | a | b
Output:

 Non-terminals: {S}
 Terminals: {a, b}
 Productions: {S → Sab, S → ab, S → a, S → b}
 Start symbol: S

Program:
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAX 100

int isNonTerminal(char ch) {


return isupper(ch);
}

int isTerminal(char ch) {


return islower(ch) || isdigit(ch) || ispunct(ch);
}

int main() {
Sanjeet Mijar Symbol No.: 28108/078
FILE *fp;
char line[MAX];
char nonTerminals[50], terminals[50];
char productions[50][MAX];
int ntCount = 0, tCount = 0, pCount = 0;

// Open file
fp = fopen("grammar.txt", "r");
if (fp == NULL) {
printf("Error opening file.\n");
return 1;
}

printf("Reading grammar from file...\n");

while (fgets(line, sizeof(line), fp)) {


// Remove newline character if present
line[strcspn(line, "\n")] = '\0';

// Skip empty lines


if (strlen(line) == 0) continue;

char lhs = line[0];


int foundNT = 0;

// Verify the line has a production symbol


if (strstr(line, "?") == NULL && strstr(line, "->") == NULL) {
printf("Warning: Invalid production format in line: %s\n", line);
continue;
}

// Store non-terminal if not already present


for (int i = 0; i < ntCount; i++) {
if (nonTerminals[i] == lhs) {
foundNT = 1;
break;
}
}
if (!foundNT && isNonTerminal(lhs)) {
nonTerminals[ntCount++] = lhs;
}

// Store production
strcpy(productions[pCount++], line);
Sanjeet Mijar Symbol No.: 28108/078

// Extract terminals from RHS


char *arrow = strstr(line, "?");
if (!arrow) arrow = strstr(line, "->"); // support both ? and ->
if (arrow) {
arrow += (arrow[1] == '>' || arrow[1] == '-') ? 2 : 1; // handle both ? and ->
while (*arrow) {
if (isTerminal(*arrow) && *arrow != ' ') {
int exists = 0;
for (int i = 0; i < tCount; i++) {
if (terminals[i] == *arrow) {
exists = 1;
break;
}
}
if (!exists) {
terminals[tCount++] = *arrow;
}
}
arrow++;
}
}
}

fclose(fp);

// Output results
printf("\nSet of Non-terminals = { ");
for (int i = 0; i < ntCount; i++) {
printf("%c", nonTerminals[i]);
if (i < ntCount - 1) printf(", ");
}
printf(" }\n");

printf("Set of Terminals = { ");


for (int i = 0; i < tCount; i++) {
printf("%c", terminals[i]);
if (i < tCount - 1) printf(", ");
}
printf(" }\n");

printf("Set of Productions = {\n");


for (int i = 0; i < pCount; i++) {
printf(" %s\n", productions[i]);
Sanjeet Mijar Symbol No.: 28108/078
}
printf("}\n");

printf("Starting Symbol = { %c }\n", nonTerminals[0]);

// Student information
printf("\nName: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");
printf("Lab No.: 6\n");
printf("Program: CFG Analyzer\n");

return 0;
}
Output:

LAB 6. Write a program to realize the concept of loop optimization in compiler


optimization in following cases, with respect to running time only.
a. Code Motion
Sanjeet Mijar Symbol No.: 28108/078
Theory:
Move invariant code outside loops:

 Identify computations that don't change within loop


 Move them before/after the loop
 Reduces redundant computations

Example:
In Program1, c = d+e and f = g+h are loop-invariant
Moving them out (Program2) reduces operations from 3×n to 2 + n

Program:
#include <stdio.h>
#include <time.h>

// Function to print student information


void print_student_info() {
printf("\n\n--- Student Information ---\n");
printf("Name: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");
printf("Lab No.: 6\n");
printf("Program: Loop Optimization Demonstration\n");
}

// Code Motion Optimization Demonstration


void code_motion_demo() {
printf("\n=== Code Motion Optimization ===\n");

clock_t start, end;


double time1, time2;
int a, b = 5, c, d = 3, e = 4, f, g = 7, h = 8;
const long iterations = 1000000000L;
int i;

// Program 1 - Without optimization


start = clock();
for(i = 0; i < iterations; i++) {
a = b + i;
c = d + e; // These computations are loop invariant
f = g + h; // These computations are loop invariant
}
end = clock();
Sanjeet Mijar Symbol No.: 28108/078
time1 = ((double)(end - start)) / CLOCKS_PER_SEC;

// Program 2 - With code motion optimization


start = clock();
// Move invariant computations outside the loop
c = d + e;
f = g + h;

for(i = 0; i < iterations; i++) {


a = b + i;
}
end = clock();
time2 = ((double)(end - start)) / CLOCKS_PER_SEC;

printf("Original loop time: %.4f seconds\n", time1);


printf("Optimized loop time: %.4f seconds\n", time2);
printf("Improvement: %.2f%%\n", (time1 - time2)/time1 * 100);
}

// Loop Jamming Optimization Demonstration


void loop_jamming_demo() {
printf("\n=== Loop Jamming Optimization ===\n");

clock_t start, end;


double time1, time2;
const int size = 10000000;
int a[size], b[size], c[size], d[size];
int i;

// Initialize arrays
for(i = 0; i < size; i++) {
b[i] = i;
c[i] = i * 2;
d[i] = i + 1;
}

// Program 1 - Separate loops


start = clock();
for(i = 0; i < size; i++) {
a[i] = b[i] + 1;
}
for(i = 0; i < size; i++) {
c[i] = d[i] * 2;
}
end = clock();
Sanjeet Mijar Symbol No.: 28108/078
time1 = ((double)(end - start)) / CLOCKS_PER_SEC;

// Program 2 - With loop jamming


start = clock();
for(i = 0; i < size; i++) {
a[i] = b[i] + 1;
c[i] = d[i] * 2;
}
end = clock();
time2 = ((double)(end - start)) / CLOCKS_PER_SEC;

printf("Separate loops time: %.4f seconds\n", time1);


printf("Jammed loop time: %.4f seconds\n", time2);
printf("Improvement: %.2f%%\n", (time1 - time2)/time1 * 100);
}

int main() {
printf("==== Loop Optimization Demonstrations ====\n");

// Demonstrate both optimization techniques


code_motion_demo();
loop_jamming_demo();

// Print student information


print_student_info();

return 0;
}
Output:

b. Loop Jamming
Sanjeet Mijar Symbol No.: 28108/078
Theory:
Combine adjacent loops with same iteration space:

 Reduces loop overhead


 Improves cache locality
 Applicable when no data dependencies between loops

Program:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define SIZE 10000000

void print_student_info() {
printf("\n\n--- Student Information ---\n");
printf("Name: Sanjeet Mijar\n");
printf("Symbol No.: 28108/078\n");
printf("Lab No.: 6\n");
printf("Program: Loop Jamming Optimization\n");
}

int main() {
clock_t start, end;
double time_separate, time_jammed;
int *a = malloc(SIZE * sizeof(int));
int *b = malloc(SIZE * sizeof(int));
int *c = malloc(SIZE * sizeof(int));
int *d = malloc(SIZE * sizeof(int));

if (!a || !b || !c || !d) {
printf("Memory allocation failed!\n");
return 1;
Sanjeet Mijar Symbol No.: 28108/078
}

// Initialize arrays
for (int i = 0; i < SIZE; i++) {
b[i] = i;
c[i] = i * 2;
d[i] = i + 1;
}

printf("=== Loop Jamming Optimization ===\n");

// Method 1: Separate loops


start = clock();
for (int i = 0; i < SIZE; i++) {
a[i] = b[i] + 1;
}
for (int i = 0; i < SIZE; i++) {
c[i] = d[i] * 2;
}
end = clock();
time_separate = ((double)(end - start)) / CLOCKS_PER_SEC;

// Method 2: Jammed loop


start = clock();
for (int i = 0; i < SIZE; i++) {
a[i] = b[i] + 1;
c[i] = d[i] * 2;
}
end = clock();
time_jammed = ((double)(end - start)) / CLOCKS_PER_SEC;

printf("Separate loops time: %.4f seconds\n", time_separate);


Sanjeet Mijar Symbol No.: 28108/078
printf("Jammed loop time: %.4f seconds\n", time_jammed);
printf("Performance improvement: %.2f%%\n",
(time_separate - time_jammed) / time_separate * 100);

// Free allocated memory


free(a);
free(b);
free(c);
free(d);

print_student_info();
return 0;
}
Output:

You might also like