DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Student Name: Kanchana Bhandari UID: 22BCS10178
Branch: BE CSE Section/Group: IOT-621-B
Semester: 6th Date of Performance:20-04-25
Subject Name: Parallel & Distributed Computing Subject Code: 22CSH-352
ASSIGNMENT 2
Question no.1: Illustrate how data parallelism enhances computational speed in
large-scale processing.
Ans: Data Parallelism means dividing large data into smaller chunks and processing each
chunk simultaneously on multiple processors. Each processor performs the same task
but on a different set of data.
How It Enhances Speed in Large-Scale Processing:
i. Parallel Execution:
Multiple processors work together at the same time, reducing total processing time.
ii. Better Resource Utilization:
All available cores or processors are used efficiently.
iii. Scalability:
As data size increases, more processors can be added to maintain fast performance.
iv. Ideal for Repetitive Tasks:
Operations like matrix calculations, image processing, or data filtering benefit a lot
v. Divide and Conquer Approach
Large data (like gigabytes of logs, images, or transactions) is split into smaller parts and
processed in parallel, instead of one-by-one.
vi. Low Communication Overhead
Each processor works on its own chunk with minimal need to communicate with others,
which keeps things fast and simple.
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Question no.2: Discuss the advantages and limitations of shared memory
multiprocessors and distributed memory networks in terms of scalability and data
consistency.
Ans:
Shared Memory Multiprocessors :
These systems have one main memory shared by all processors. Examples: Multicore CPUs
in desktops or servers.
Advantages:
i. All processors share the same memory space → data exchange is fast and simple.
ii. Developers don’t need to manage data movement → easier to write and debug programs.
iii. Works well when there are only a few processors (e.g., 2–16 cores).
iv. Memory updates are visible to all processors (with cache coherence mechanisms).
Limitations:
i. As the number of processors increases, they compete for shared memory, causing
bottlenecks.
ii. Requires special hardware (cache coherence, memory access control) → expensive to
build at large scale.
iii. Cache coherence becomes harder to maintain with more processors.
Distributed Memory Networks
Each processor (node) has its own local memory and communicates via a network (e.g.,
MPI, sockets). Examples: Supercomputers, cloud clusters.
Advantages
i. Each processor has its own local memory → easy to add more processors without
memory bottlenecks.
ii. Cheaper to scale by connecting independent machines (e.g., in clusters or grids).
iii. Ideal for massive parallel processing, like in scientific computing or big data.
Limitations
i. Programmers must handle explicit data communication (e.g., using MPI).
ii. Developers must ensure data consistency between different memory spaces.
iii. Transferring data between machines is slower than shared memory access.
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Question no.3: Compare the performance evaluation of single-program execution
versus multiple-program execution in parallel computing. Identify and explain the
significance of two widely used benchmarking techniques for assessing parallel
processor performance.
Ans:
1. Single-Program Execution
In single-program execution, one task or program is executed by multiple processors in
parallel.
Process: The task is split into smaller sub-tasks (data parallelism or task parallelism), and
each processor works on a part of the task.
Advantages:
i. Simple: Easier to implement because you only focus on one task.
ii. Memory Efficiency: All processors share the same task and often the same memory space,
so data sharing is easier.
iii. Higher throughput for single tasks: Ideal for tasks like matrix operations, large-scale data
processing, or scientific simulations.
Limitations:
i. Scalability issues: As the number of processors increases, the communication overhead
also grows.
ii. Less flexible: The system is fixed on one task, so it's not as versatile when dealing with
multiple independent tasks.
2. Multiple-Program Execution
In multiple-program execution, multiple independent programs run simultaneously,
typically on different processors or cores.
Process: The system runs several tasks concurrently, each task potentially being a
completely different program or an independent instance of a task.
Advantages:
i. Better resource utilization: Multiple programs use the available processing resources
efficiently.
ii. Increased flexibility: It can handle a variety of tasks at once (e.g., running different
simulations, data analysis tasks, or user applications).
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
iii. Improved throughput: Useful in systems where you need to execute multiple jobs or
handle multiple users simultaneously.
Limitations:
i. Increased complexity: More challenging to manage as multiple programs may need
different resources (memory, I/O, etc.).
ii. Context switching: Switching between tasks can lead to performance overhead, reducing
overall efficiency.
iii. Communication overhead: If programs need to communicate with each other, managing
this across multiple memory spaces (distributed systems) can be tricky.
Question no.4: Discuss dynamic and static task scheduling techniques and their
impact on resource utilization in distributed systems. Propose a real-world scenario
where effective load balancing improves overall system performance.
Ans: In distributed systems, task scheduling is used to decide which processor/node does
which task and when. The goal is to maximize performance, reduce idle time, and utilize
resources efficiently.
Static Task Scheduling:
Tasks are assigned to processors before execution. The schedule is fixed and does not
change during runtime.
Features:
i. Requires knowledge of the task load and processor capabilities in advance.
ii. Once assigned, tasks don't move between processors.
Advantages:
i. Simple and low overhead.
ii. Works well when task sizes and system conditions are predictable.
Limitations:
i. Poor load balancing if actual runtime differs from expectations.
ii. Not suitable for dynamic or unpredictable workloads.
Dynamic Task Scheduling: Tasks are assigned to processors at runtime, based on
availability and system load.
Features:
i. Uses real-time information to decide task placement.
ii. Adapts to workload changes and system failures.
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Advantages:
i. Better load balancing and resource utilization.
ii. Can handle uneven or unpredictable workloads efficiently.
Limitations:
i. More complex to implement.
ii. Slight overhead due to runtime decision-making.
Question no.5: Explain the role of MapReduce and Apache Spark in processing large-
scale data in the cloud.
Ans:
1. Identity Management (IAM)
Controls who can access what in a cloud environment.
Key Functions:
Assigns permissions to users, apps, and devices.
Enforces role-based access control (RBAC).
Keeps logs of user activities for audits.
Importance:
Prevents unauthorized access.
Limits damage from compromised accounts.
Ensures users only access what they need.
Example: AWS IAM, Azure Active Directory.
2. Multi-Factor Authentication (MFA)
Adds extra layer of security beyond just username & password.
How it works:
Requires at least two forms of verification:
- Password (something you know)
- OTP, phone notification, or biometric (something you have/are)
Importance:
Blocks attackers even if passwords are leaked.
Protects admin/root access to cloud systems.
Reduces risk of phishing and brute-force attacks.
Example: Google Authenticator, Duo Security.
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
3. Firewalls
Monitors and filters incoming/outgoing traffic based on rules.
Types in Cloud:
Network firewalls: Control traffic between subnets.
Web Application Firewalls (WAF): Protect web apps from attacks (e.g., SQL injection,
XSS).
Importance:
Stops unauthorized access and malicious traffic.
Creates security zones in cloud environments.
Works with intrusion detection systems (IDS) for real-time alerts.
Example: AWS WAF, Google Cloud Armor.
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
COMPLEX PROBLEMS
CG LAB
Student Name: Vaibhav UI D 22BCS13798
Section/Group: 621-A
Date :10-04-25
Q1 .
Generate a dynamic analog clock with ticking second, minute, and hour hands.
Implemetation/Code
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <time.h>
#include <dos.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
void calculate_hand_pos(int cx, int cy, int radius, double angle_deg, int &x, int &y) {
double angle_rad = (90.0 - angle_deg) * M_PI / 180.0;
x = cx + (int)(radius * cos(angle_rad));
y = cy - (int)(radius * sin(angle_rad));
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TurboC3\\BGI");
int mid_x = getmaxx() / 2;
int mid_y = getmaxy() / 2;
int clock_radius = (getmaxy() < getmaxx() ? getmaxy() : getmaxx()) / 3;
int hour_hand_len = (int)(clock_radius * 0.5);
int min_hand_len = (int)(clock_radius * 0.7);
int sec_hand_len = (int)(clock_radius * 0.9);
int hx, hy, mx, my, sx, sy;
time_t raw_time;
struct tm *current_time;
while (!kbhit()) {
time(&raw_time);
current_time = localtime(&raw_time);
int hours = current_time->tm_hour;
int minutes = current_time->tm_min;
int seconds = current_time->tm_sec;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
double sec_angle = seconds * 6.0;
double min_angle = (minutes + seconds / 60.0) * 6.0;
double hour_angle = ((hours % 12) + minutes / 60.0) * 30.0;
calculate_hand_pos(mid_x, mid_y, sec_hand_len, sec_angle, sx, sy);
calculate_hand_pos(mid_x, mid_y, min_hand_len, min_angle, mx, my);
calculate_hand_pos(mid_x, mid_y, hour_hand_len, hour_angle, hx, hy);
cleardevice();
setcolor(WHITE);
circle(mid_x, mid_y, clock_radius);
setcolor(YELLOW);
for (int i = 0; i < 12; ++i) {
int start_x, start_y, end_x, end_y;
double marker_angle_deg = i * 30.0;
calculate_hand_pos(mid_x, mid_y, (int)(clock_radius * 0.9), marker_angle_deg,
start_x, start_y);
calculate_hand_pos(mid_x, mid_y, clock_radius, marker_angle_deg, end_x, end_y);
line(start_x, start_y, end_x, end_y);
}
setcolor(WHITE);
circle(mid_x, mid_y, 3);
floodfill(mid_x, mid_y, WHITE);
setcolor(LIGHTBLUE);
setlinestyle(SOLID_LINE, 0, THICK_WIDTH);
line(mid_x, mid_y, hx, hy);
setcolor(GREEN);
setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
line(mid_x, mid_y, mx, my);
setcolor(RED);
line(mid_x, mid_y, sx, sy);
delay(100);
}
getch();
closegraph();
return 0;
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Q2 .
Implement an interactive tool to draw concentric circles using the midpoint algorithm with
dynamic radius input.
Implemetation/Code
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
void plot_circle_points(int xc, int yc, int x, int y, int color) {
putpixel(xc + x, yc + y, color);
putpixel(xc - x, yc + y, color);
putpixel(xc + x, yc - y, color);
putpixel(xc - x, yc - y, color);
putpixel(xc + y, yc + x, color);
putpixel(xc - y, yc + x, color);
putpixel(xc + y, yc - x, color);
putpixel(xc - y, yc - x, color);
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
void drawCircleMidpoint(int xc, int yc, int r, int color) {
if (r <= 0) return;
int x = 0;
int y = r;
int p = 1 - r;
plot_circle_points(xc, yc, x, y, color);
while (x < y) {
x++;
if (p < 0) {
p = p + 2 * x + 1;
} else {
y--;
p = p + 2 * (x - y) + 1;
}
plot_circle_points(xc, yc, x, y, color);
}
}
int getRadiusInput(int prompt_x, int prompt_y) {
char input_buffer[10];
int buffer_index = 0;
char display_char[2] = {0};
int current_input_x = prompt_x;
memset(input_buffer, 0, sizeof(input_buffer));
setfillstyle(SOLID_FILL, BLACK);
int clear_y = prompt_y;
int clear_height = textheight("M") + 5;
int clear_width = getmaxx() - prompt_x - 10;
bar(prompt_x, clear_y, prompt_x + clear_width, clear_y + clear_height);
setcolor(YELLOW);
outtextxy(prompt_x, prompt_y, "Enter Radius (1-300, Esc=Exit): ");
current_input_x += textwidth("Enter Radius (1-300, Esc=Exit): ");
while (buffer_index < sizeof(input_buffer) - 1) {
int key = getch();
if (key == 27) {
return 0;
} else if (key == 13) {
if (buffer_index > 0) {
break;
}
return 0;
} else if (key == 8 && buffer_index > 0) {
buffer_index--;
input_buffer[buffer_index] = '\0';
setcolor(BLACK);
display_char[0] = 'W';
int char_width = textwidth(display_char);
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
current_input_x -= char_width;
if (current_input_x < 0) current_input_x = 0;
bar(current_input_x, prompt_y, current_input_x + char_width, prompt_y + textheight("0"));
} else if (isdigit(key) && buffer_index < sizeof(input_buffer) - 1) {
input_buffer[buffer_index] = (char)key;
buffer_index++;
input_buffer[buffer_index] = '\0';
setcolor(WHITE);
display_char[0] = (char)key;
outtextxy(current_input_x, prompt_y, display_char);
current_input_x += textwidth(display_char);
}
}
input_buffer[buffer_index] = '\0';
if (strlen(input_buffer) > 0) {
int radius = atoi(input_buffer);
if (radius > 0 && radius < 32767) {
return radius;
}
}
return 0;
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TURBOC3\\BGI");
int errorcode = graphresult();
if (errorcode != grOk) {
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Please ensure the BGI path in initgraph is correct for your system.\n");
printf("Press any key to halt:");
getch();
exit(1);
}
int mid_x = getmaxx() / 2;
int mid_y = getmaxy() / 2;
int radius = 0;
int prompt_x = 10;
int prompt_y = 10;
int status_y = prompt_y + 20;
do {
radius = getRadiusInput(prompt_x, prompt_y);
if (radius > 0) {
setcolor(WHITE);
drawCircleMidpoint(mid_x, mid_y, radius, WHITE);
setfillstyle(SOLID_FILL, BLACK);
int status_clear_width = getmaxx() - prompt_x - 10;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
bar(prompt_x, status_y, prompt_x + status_clear_width, status_y + textheight("M"));
char radius_text[30];
sprintf(radius_text, "Drew Radius: %d. Press key...", radius);
setcolor(LIGHTGREEN);
outtextxy(prompt_x, status_y, radius_text);
getch();
} else {
break;
}
} while (radius > 0);
cleardevice();
setcolor(YELLOW);
outtextxy(mid_x - textwidth("Exiting...")/2, mid_y, "Exiting...");
closegraph();
return 0;
}
Q3.
Implement a multi-viewport display that shows the same object in different viewports
(scaled, translated, rotated).
Implemetation/Code
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
typedef struct {
double x, y;
} Point;
Point rotate_point(Point p, double angle_deg, double cx, double cy) {
double angle_rad = angle_deg * M_PI / 180.0;
double cos_a = cos(angle_rad);
double sin_a = sin(angle_rad);
Point rotated_p;
double temp_x = p.x - cx;
double temp_y = p.y - cy;
rotated_p.x = temp_x * cos_a - temp_y * sin_a;
rotated_p.y = temp_x * sin_a + temp_y * cos_a;
rotated_p.x += cx;
rotated_p.y += cy;
return rotated_p;
}
Point scale_point(Point p, double sx, double sy, double cx, double cy) {
Point scaled_p;
double temp_x = p.x - cx;
double temp_y = p.y - cy;
scaled_p.x = temp_x * sx;
scaled_p.y = temp_y * sy;
scaled_p.x += cx;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
scaled_p.y += cy;
return scaled_p;
}
Point translate_point(Point p, double tx, double ty) {
Point translated_p;
translated_p.x = p.x + tx;
translated_p.y = p.y + ty;
return translated_p;
}
void draw_shape(Point points[], int num_points, int color) {
if (num_points < 2) return;
int poly_points[20];
if (num_points * 2 + 2 > 20) return;
for (int i = 0; i < num_points; ++i) {
poly_points[i * 2] = (int)(points[i].x + 0.5);
poly_points[i * 2 + 1] = (int)(points[i].y + 0.5);
}
poly_points[num_points * 2] = poly_points[0];
poly_points[num_points * 2 + 1] = poly_points[1];
setcolor(color);
drawpoly(num_points + 1, poly_points);
}
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TURBOC3\\BGI");
int errorcode = graphresult();
if (errorcode != grOk) {
printf("Graphics error: %s\n", grapherrormsg(errorcode));
printf("Please ensure the BGI path in initgraph is correct for your system.\n");
printf("Press any key to halt:");
getch();
exit(1);
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
const int num_vertices = 3;
Point base_object[num_vertices] = {
{0, -30},
{-25, 20},
{25, 20}
};
Point transformed_object[num_vertices];
int screen_w = getmaxx();
int screen_h = getmaxy();
int vp_w = screen_w / 2;
int vp_h = screen_h / 2;
int vp[4][4] = {
{0, 0, vp_w - 1, vp_h - 1},
{vp_w, 0, screen_w - 1, vp_h - 1},
{0, vp_h, vp_w - 1, screen_h - 1},
{vp_w, vp_h, screen_w - 1, screen_h - 1}
};
for (int i = 0; i < 4; ++i) {
int j;
int x1 = vp[i][0];
int y1 = vp[i][1];
int x2 = vp[i][2];
int y2 = vp[i][3];
int current_vp_w = x2 - x1 + 1;
int current_vp_h = y2 - y1 + 1;
double vp_cx = (double)current_vp_w / 2.0;
double vp_cy = (double)current_vp_h / 2.0;
for (j = 0; j < num_vertices; ++j) {
transformed_object[j] = base_object[j];
}
switch (i) {
case 0:
break;
case 1:
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
for (j = 0; j < num_vertices; ++j) {
transformed_object[j] = scale_point(transformed_object[j], 1.5, 1.5, 0, 0);
}
break;
case 2:
for (j = 0; j < num_vertices; ++j) {
transformed_object[j] = rotate_point(transformed_object[j], 45.0, 0, 0);
}
break;
case 3:
for (j = 0; j < num_vertices; ++j) {
transformed_object[j] = scale_point(transformed_object[j], 0.7, 0.7, 0, 0);
transformed_object[j] = translate_point(transformed_object[j], -15, -10);
}
break;
}
for (j = 0; j < num_vertices; ++j) {
transformed_object[j] = translate_point(transformed_object[j], vp_cx, vp_cy);
}
setviewport(x1, y1, x2, y2, 1);
setcolor(DARKGRAY);
rectangle(0, 0, current_vp_w - 1, current_vp_h - 1);
draw_shape(transformed_object, num_vertices, WHITE);
char info[10];
sprintf(info, "VP %d", i + 1);
setcolor(YELLOW);
outtextxy(5, 5, info);
}
setviewport(0, 0, screen_w - 1, screen_h - 1, 1);
getch();
closegraph();
return 0;
}
4. Implement a shape-drawing tool that allows real-time drawing of shapes with mouse drag
functionality.
Implementation / Code
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
#include <graphics.h>
#include <dos.h>
#include <conio.h>
int main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\TURBOC3\\BGI");
int x0, y0, x1, y1;
int isDrawing = 0;
int mx, my, button;
setcolor(WHITE);
setbkcolor(BLACK);
cleardevice();
while (!kbhit()) {
button = bioskey(1); // check keyboard to break loop
if (ismouseclick(WM_LBUTTONDOWN)) {
getmouseclick(WM_LBUTTONDOWN, x0, y0);
isDrawing = 1;
} else if (ismouseclick(WM_LBUTTONUP)) {
getmouseclick(WM_LBUTTONUP, x1, y1);
rectangle(x0, y0, x1, y1);
isDrawing = 0;
} else if (isDrawing) {
getmousepos(&button, &mx, &my);
cleardevice();
rectangle(x0, y0, mx, my);
}
}
getch();
closegraph();
return 0;
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
OUTPUT
5 Perform compound transformations on arbitrary polygons (not just triangles), maintaining
the order of operations.
CODE
#include <iostream.h>
#include <graphics.h>
#include <math.h>
#include <conio.h>
#define MAX 10
// Structure to hold a point
struct Point {
float x, y;
};
// Function to multiply a point by a 3x3 matrix
void multiplyMatrix(Point &p, float mat[3][3]) {
float x = p.x, y = p.y;
p.x = mat[0][0]*x + mat[0][1]*y + mat[0][2];
p.y = mat[1][0]*x + mat[1][1]*y + mat[1][2];
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
// Function to apply a transformation matrix to a polygon
void applyTransformation(Point poly[], int n, float mat[3][3]) {
for (int i = 0; i < n; i++) {
multiplyMatrix(poly[i], mat);
}
}
// Function to draw polygon
void drawPolygon(Point poly[], int n, int color) {
setcolor(color);
for (int i = 0; i < n - 1; i++) {
line(poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y);
}
line(poly[n-1].x, poly[n-1].y, poly[0].x, poly[0].y); // close polygon
}
// Function to create a translation matrix
void translationMatrix(float tx, float ty, float mat[3][3]) {
mat[0][0] = 1; mat[0][1] = 0; mat[0][2] = tx;
mat[1][0] = 0; mat[1][1] = 1; mat[1][2] = ty;
mat[2][0] = 0; mat[2][1] = 0; mat[2][2] = 1;
}
// Function to create a scaling matrix
void scalingMatrix(float sx, float sy, float mat[3][3]) {
mat[0][0] = sx; mat[0][1] = 0; mat[0][2] = 0;
mat[1][0] = 0; mat[1][1] = sy; mat[1][2] = 0;
mat[2][0] = 0; mat[2][1] = 0; mat[2][2] = 1;
}
// Function to create a rotation matrix (theta in degrees)
void rotationMatrix(float theta, float mat[3][3]) {
float rad = theta * 3.14159 / 180.0;
mat[0][0] = cos(rad); mat[0][1] = -sin(rad); mat[0][2] = 0;
mat[1][0] = sin(rad); mat[1][1] = cos(rad); mat[1][2] = 0;
mat[2][0] = 0; mat[2][1] = 0; mat[2][2] = 1;
}
// Function to multiply two 3x3 matrices
void multiplyMatrix3x3(float a[3][3], float b[3][3], float result[3][3]) {
for (int i=0; i<3; i++)
for (int j=0; j<3; j++) {
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
result[i][j] = 0;
for (int k=0; k<3; k++)
result[i][j] += a[i][k] * b[k][j];
}
}
void main() {
int gd = DETECT, gm;
initgraph(&gd, &gm, "C:\\Turboc3\\BGI");
int n;
Point poly[MAX], original[MAX];
cout << "Enter number of vertices of polygon: ";
cin >> n;
for (int i = 0; i < n; i++) {
cout << "Enter x and y for point " << i+1 << ": ";
cin >> poly[i].x >> poly[i].y;
original[i] = poly[i]; // store original for comparison
}
// Draw original polygon in WHITE
drawPolygon(original, n, WHITE);
// Create transformation matrices
float T[3][3], S[3][3], R[3][3], temp[3][3], finalMatrix[3][3];
translationMatrix(100, 50, T); // Translate by (100, 50)
scalingMatrix(1.5, 1.5, S); // Scale by 1.5
rotationMatrix(45, R); // Rotate by 45 degrees
// Combine matrices: M = T * R * S (order matters!)
multiplyMatrix3x3(R, S, temp); // temp = R * S
multiplyMatrix3x3(T, temp, finalMatrix); // finalMatrix = T * (R * S)
// Apply the final compound transformation
applyTransformation(poly, n, finalMatrix);
// Draw transformed polygon in YELLOW
drawPolygon(poly, n, YELLOW);
getch();
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
closegraph();
}
OUTPUT