In this post, we are going to explore the fma function in C++ along with its syntax, parameters, and illustrations.
Introduction:
The C function fma is created to execute a fused multiply-add operation which calculates (x * y) + z in one step, minimizing potential rounding discrepancies that may arise when multiplication and addition are done independently. This functionality is especially valuable in precision-focused numerical scenarios.
Syntax:
It has the following syntax:
#include <cmath>
float fma (float x, float y, float z);
double fma (double x, double y, double z);
Parameters:
It has the following parameters:
x: multiplier.
y: multiplier.
z: addition.
Return value: The outcome of the combined multiplication calculation: (x * y) + z.
It implements the Fused-multiply-add technique while maintaining computational accuracy. The fma-c function computes (x * y) + z more efficiently compared to explicitly implementing this operation in a C++ code. Since C++11, the return type of fma-c has been modified to long double; if any of the inputs are long double, the return type becomes double or float, based on the input types.
Fma Prototype [As of C++11 standard]:
#include <cmath>
float fma (float x, float y, float z);
double fma (double x, double y, double z);
It implies that the FMA function is capable of handling both float and double data types simultaneously. This function accepts three parameters (x, y, and z) and performs the operation (x * y) + z with enhanced accuracy, eliminating the potential rounding errors that could arise if the multiplication and addition were executed separately. When dealing with integer values, it may be necessary to convert them to floating point types prior to utilizing the fma function. It's essential to acknowledge that fma is considered a low-level function and may not be essential in every scenario. In numerous cases, standard multiplication and addition operations suffice and can be efficiently optimized by the compiler. The utilization of Fma tends to be more crucial in numerical applications where precision plays a vital role.
Error Handling in fma Prototype:
The fma function typically does not incorporate specific error-handling mechanisms. It primarily aims to offer a combined multiplication operation without rounding in between. Nevertheless, in scenarios where the fma function is applied within a more extensive program, it becomes essential to address potential floating-point exceptions or exceptional error situations. Below are some fundamental factors to bear in mind when managing errors while utilizing fma or similar floating-point functions.
Floating-point exceptions like overflow, underflow, division by zero, and invalid operation may occur during mathematical calculations. In C++, we have the ability to define the handling of these exceptions by utilizing the std::fetestexcept and std::feclearexcept functions within the context of exception control.
Example:
Let's consider a scenario to demonstrate the application of the fma function in the C++ programming language.
#include <iostream>
#include <cfenv>
#include <cmath>
int main() {
std::feclearexcept(FE_ALL_EXCEPT);
float result = std::fma(1.0f, 2.0f, std::numeric_limits<float>::infinity());
if (std::fetestexcept(FE_OVERFLOW)) {
std::cerr << "Overflow occurred!" << std::endl;
}
// Handle other exceptions as needed...
return 0;
}
Output:
Overflow occurred!
- Special cases:
Take into account exceptional scenarios like handling NaN (not a number) or Inf (infinity) values that could arise from specific computations.
Example:
#include <iostream>
#include <cmath>
int main() {
double x = 1.0;
double y = std::numeric_limits<double>::quiet_NaN();
double z = 2.0;
double result = std::fma(x, y, z);
if (std::isnan(result)) {
std::cerr << "Result is NaN!" << std::endl;
}
// Handle other special cases.
return 0;
}
Output:
Result is NaN!
- Checking input values:
It is advisable to verify the correctness of input parameters prior to utilizing the fma function to prevent any unforeseen outcomes.
Example:
#include <iostream>
#include <cmath>
int main() {
double x = 1.0;
double y = 2.0;
double z = std::numeric_limits<double>::infinity();
if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z)) {
std::cerr << "Invalid input values!" << std::endl;
return 1; // or handle the error appropriately
}
double result = std::fma(x, y, z);
// Continue with the rest of the code...
return 0;
}
Program:
Let's consider a scenario to demonstrate the application of the fma function in C++.
#include <iostream>
#include<math.h>
using namespace std;
int main()
{
int x= 2;
int y=3;
int z=4;
std::cout << "Values of x,y,z are :" <<x<<","<<y<<","<<z<< std::endl;
cout<<"fma(x,y,z) : "<<fma(x,y,z);
return 0;
}
Output:
Values of x,y,z are :2,3,4
fma(x,y,z) : 10
Explanation:
include<iostream>:
This statement includes the input/output stream library essential for executing input/output tasks.
include <math>:
This statement pertains to the mathematical library utilized for mathematical calculations. The fused multiply-add (fma) operation is included within the math library.
using namespace std:
This statement signifies that the program utilizes components from the std namespace (standard). This enables the utilization of standard C++ functions without the need to explicitly mention a namespace on every occasion.
int main {/ ... / }:
This serves as the primary function initiating the program's execution.
int x = 2;
int y = 3;
These lines establish and assign values to three integer variables x, y, and z, with the values 2, 3, and 4, in that order.
The x, y, and z values are output as "x", "y", and "z" using the std::endl statement. This code line displays the x, y, and z values on the console.
cout "fma (x, y, z): " fma(x, y, z);:
This code line evaluates the multiplication of the total of x, y, and z with the fma function and displays the outcome on the console.
return 0;
It signifies that the software executed without errors and sends a return value of 0 to the OS. The primary objective of this snippet is to demonstrate the functionality of the fma function, which handles fused multiply-add operations. Subsequently, the output is displayed on the terminal showcasing the original values of x, y, and z.