slow program performance

Greetings readers. some time ago I made a program that draws 2 functions and paints their intersection, but it all works very slowly, it would be nice to modify the program to make it work faster, but how I don’t know honestly
program code:

//Using SDL, SDL_image, standard IO, and strings
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 640;
 
//Starts up SDL and creates window
bool init();
 
//Frees media and shuts down SDL
void close();
 
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
 
//The window renderer
SDL_Renderer* gRenderer = NULL;
 
bool init()
{
    //Initialization flag
    bool success = true;
 
    //Initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
        success = false;
    }
    else
    {
        //Set texture filtering to linear
        if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
        {
            printf("Warning: Linear texture filtering not enabled!");
        }
 
        //Create window
        gWindow = SDL_CreateWindow("SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
        if (gWindow == NULL)
        {
            printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
            success = false;
        }
        else
        {
            //Create renderer for window
            gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
            if (gRenderer == NULL)
            {
                printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
                success = false;
            }
            else
            {
                //Initialize renderer color
                SDL_SetRenderDrawColor(gRenderer, 255, 255, 255, 0);
            }
        }
    }
    return success;
}
 
void close()
{
    //Destroy window
    SDL_DestroyRenderer(gRenderer);
    SDL_DestroyWindow(gWindow);
    gWindow = NULL;
    gRenderer = NULL;
 
    SDL_Quit();
}
 
int main(int argc, char* args[])
{
    //Start up SDL and create window
    if (!init())
    {
        printf("Failed to initialize!\n");
    }
    else
    {
        //Main loop flag
        bool quit = false;
 
        //Event handler
        SDL_Event e;
 
        //While application is running
        while (!quit)
        {
            //Handle events on queue
            while (SDL_PollEvent(&e) != 0)
            {
                //User requests quit
                if (e.type == SDL_QUIT)
                {
                    quit = true;
                }
            }
            float x,y,x1,y1;
            float offset = 100;
            float scale = 8;
            int xPointArr[1801];
            int yPointArr[1801];
            //Clear screen
            SDL_RenderClear(gRenderer);
 
            SDL_SetRenderDrawColor(gRenderer, 0, 255, 0, 255);
            SDL_RenderDrawLine(gRenderer, 0, offset - 2 * scale, 900, offset - 2 * scale);
 
            for (int i = 0, j = 1800; i < 1800; i++, j--)
            {
                x = i - 900;
                y = -(sqrt(25 - x * x / 50));
 
                xPointArr[i] = x + offset;
                yPointArr[i] = scale * y + offset;
 
                SDL_SetRenderDrawColor(gRenderer, 255, 0, 0, 255);
                if (yPointArr[i] < offset - 2 * scale)
                    SDL_RenderDrawLine(gRenderer, x + offset, scale * y + offset, 100, scale * (-(sqrt(25 - (j - 900) * (j - 900) / 50))) + offset);
 
                SDL_SetRenderDrawColor(gRenderer, 255, 255, 255, 255);
                SDL_RenderDrawLine(gRenderer, x + offset, scale * y + offset, (x + 1) + offset, scale * (-(sqrt(25 - (x + 1) * (x + 1) / 50))) + offset);
            }
 
            
 
            SDL_RenderSetLogicalSize(gRenderer, 180, 180);
            SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0xFF);
            //Update screen
            SDL_RenderPresent(gRenderer);
        }
    }
 
    //Free resources and close SDL
    close();
 
    return 0;
}

Hello, I will give you some tips:
1–arrays of many elements like the X/yPointArr, must be avoided recreated on each loop. To avoid recreate them, you can create it outside of while and just set or update the values of array.
Basically it’s the rule: --arrays go outside and it is just updated in the loop

2–recalculate only the values of the points array when some point really change its value.
That means you should only recalculate them when occours some data change, and the processing will go be lower, this is the idea from “event programming”.

3–put some SDL_Delay call between each iteration of the main loop.
Why this?
Because with the modification which I suggested, the program will runs too fast, and to give time to the user see something, the program must only update the screen in a enough time. Sometimes can be 60 milliseconds on the SDL_Delay.

When you say it’s slow how do you notice that exactly? It seems to draw the exact same thing each time. On my computer it runs at over 300 FPS.

On my machine it runs nearly with 600 FPS but there is no movement. I see only a green line with a ‘broken’ circle that is filled with red lines.

I made some tweaks to the original code to stress the usefulness of Point Number 2 in Samleo’s post above, though what I have done would not be quite practical in a real production program:

//Using SDL, SDL_image, standard IO, and strings
#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 640;
 
//Starts up SDL and creates window
bool init();
 
//Frees media and shuts down SDL
void close();
 
//The window we'll be rendering to
SDL_Window* gWindow = NULL;
 
//The window renderer
SDL_Renderer* gRenderer = NULL;
 
bool init()
{
	//Initialization flag
	bool success = true;
 
	//Initialize SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
		success = false;
	}
	else
	{
		//Set texture filtering to linear
		if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
		{
			printf("Warning: Linear texture filtering not enabled!");
		}
 
		//Create window
		gWindow = SDL_CreateWindow("SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
		if (gWindow == NULL)
		{
			printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
			success = false;
		}
		else
		{
			//Create renderer for window
			gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
			if (gRenderer == NULL)
			{
				printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
				success = false;
			}
			else
			{
				//Initialize renderer color
				SDL_SetRenderDrawColor(gRenderer, 255, 255, 255, 0);
			}
		}
	}
	return success;
}
 
void close()
{
	//Destroy window
	SDL_DestroyRenderer(gRenderer);
	SDL_DestroyWindow(gWindow);
	gWindow = NULL;
	gRenderer = NULL;
 
	SDL_Quit();
}
 
int main(int argc, char* args[])
{
	double frames = 0;
	//Start up SDL and create window
	if (!init())
	{
		printf("Failed to initialize!\n");
	}
	else
	{
		//Main loop flag
		bool quit = false;
		bool changesMade = true;
 
		//Event handler
		SDL_Event e;

		// this is a state modifyer, it just needs one call
		SDL_RenderSetLogicalSize(gRenderer, 180, 180);
 

		//While application is running
		while (!quit)
		{
			frames ++;
			//Handle events on queue
			while (SDL_PollEvent(&e) != 0)
			{
				//User requests quit
				if (e.type == SDL_QUIT)
				{
					quit = true;
				}
				else if(e.type == SDL_WINDOWEVENT)
				{
					if(e.window.event == SDL_WINDOWEVENT_RESIZED)
					{
						changesMade = true;
					}
				}
			}
			if(changesMade)
			{
				float x,y,x1,y1;
				float offset = 100;
				float scale = 8;
				int xPointArr[1801];
				int yPointArr[1801];
				//Clear screen
				SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0xFF);
				SDL_RenderClear(gRenderer);
	
				SDL_SetRenderDrawColor(gRenderer, 0, 255, 0, 255);
				SDL_RenderDrawLine(gRenderer, 0, offset - 2 * scale, 900, offset - 2 * scale);
	
				for (int i = 0, j = 1800; i < 1800; i++, j--)
				{
					x = i - 900;
					y = -(sqrt(25 - x * x / 50));
	
					xPointArr[i] = x + offset;
					yPointArr[i] = scale * y + offset;
	
					SDL_SetRenderDrawColor(gRenderer, 255, 0, 0, 255);
					if (yPointArr[i] < offset - 2 * scale)
						SDL_RenderDrawLine(gRenderer, x + offset, scale * y + offset, 100, scale * (-(sqrt(25 - (j - 900) * (j - 900) / 50))) + offset);
	
					SDL_SetRenderDrawColor(gRenderer, 255, 255, 255, 255);
					SDL_RenderDrawLine(gRenderer, x + offset, scale * y + offset, (x + 1) + offset, scale * (-(sqrt(25 - (x + 1) * (x + 1) / 50))) + offset);
				}
	 
				//Update screen
				SDL_RenderPresent(gRenderer);
				changesMade = false;
			}
		}
	}
	SDL_Log("FPS: %f", frames / (((double)SDL_GetTicks())/1000.0f));
 
	//Free resources and close SDL
	close();
 
	return 0;
}

My point is this:
Rendering and calculations are expensive and should only be done when necessary. Reuse your end result for as long as it is practical. One of the best ways to make an algorithm faster is to avoid using it whenever possible.
(In this case, I made it possible to resize the window, which seems like a good time to re-draw the image when you change window size. But even then, if you had a pre-rendered image it would be a simple RenderCopy/RenderPresent call.).

The goal is that I hope you try rendering the graph/image to a target texture that gets built once before the first frame, and after that only re-build the image when the user inputs a new function.

I think an issue you will run into is that vertical lines are kind of broken in mathematical functions, especially when you convert those functions to work in computers and integer math.
It doesn’t help that it’s even a bit finicky when you use floats as variable types since they don’t act right when they interact with integers.

// C++ code, but can be easily converted to C if needed
#include <iostream>
int main()
{
	float tom = 10/3;
	std::cout << tom << std::endl;
	float susan = 10.0f/3.0f;
	std::cout << susan << std::endl;
}

Mathematically speaking you should expect the above to output 3.333333 for both tom and susan… but in all likelyhood, your computer will output the number 3 for tom.

Check out Bresenham’s algorithm, it will help with functions of lines that are otherwise very hard to represent graphically. Bresenham's line algorithm - Wikipedia
His key concept is to rotate a function 90 degrees if the slope is approaching vertical.