How to resolve the algorithm First-class functions step by step in the C programming language

Published on 7 June 2024 03:52 AM
#C

How to resolve the algorithm First-class functions step by step in the C programming language

Table of Contents

Problem Statement

A language has first-class functions if it can do each of the following without recursively invoking a compiler or interpreter or otherwise metaprogramming:

Write a program to create an ordered collection A of functions of a real number. At least one function should be built-in and at least one should be user-defined; try using the sine, cosine, and cubing functions. Fill another collection B with the inverse of each function in A. Implement function composition as in Functional Composition. Finally, demonstrate that the result of applying the composition of each function in A and its inverse in B to a value, is the original value. (Within the limits of computational accuracy). (A solution need not actually call the collections "A" and "B". These names are only used in the preceding paragraph for clarity.)

First-class Numbers

Let's start with the solution:

Step by Step solution about How to resolve the algorithm First-class functions step by step in the C programming language

Function Pointers and Function Composition

This code demonstrates the use of function pointers and function composition in C programming.

Function Pointers:

  • A function pointer is a variable that stores the address of a function.
  • The typedef statement typedef double (*Class2Func)(double) declares a type Class2Func to represent a function that takes a double and returns a double.

Function Composition:

  • Function composition is the process of applying one function to the output of another function.
  • The code composes functions in two ways:
  1. Using a function as an argument: The function Function1 takes a function pointer f2 as an argument and applies it to a value val.
  2. Using a function returning a function: The function WhichFunc returns a function pointer based on the input idx.

Function Lists:

  • The code defines two function lists, funcListA and funcListB, which contain function pointers to various mathematical functions.

Composing Functions:

  • The function InvokeComposed composes two functions f1 and f2 and invokes the composed function with a given value.
  • The function Compose returns a Composition struct that stores the two composed functions f1 and f2.
  • The function CallComposed takes a Composition struct and a value and applies the composed function to the value.

Example Usage:

  • The main function calls the Function1 function to apply the function selected by WhichFunc to the value 3.0.
  • It then composes functions from the funcListA and funcListB lists and calls the composed functions with the value 0.9.

Second Variant Using Function Pointer Arithmetic:

This second code snippet also demonstrates function composition but using a different approach involving function pointer arithmetic.

  • The function dummy serves as a template for creating composed functions.
  • The composite function allocates memory to store a copy of dummy and modifies the function pointers within that copy to refer to the functions f and g.
  • The cube function is a simple cubic function.
  • The cbrt function returns the cube root of a number (not always available in math.h).
  • Three function lists are defined: A, B, and C, where C contains functions composed from A and B.
  • The main function loops through these lists and prints the values of composed functions applied to various input values.

Source code in the c programming language

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
 
/* declare a typedef for a function pointer */
typedef double (*Class2Func)(double);
 
/*A couple of functions with the above prototype */
double functionA( double v)
{
   return v*v*v;
}
double functionB(double v)
{
   return exp(log(v)/3);
}
 
/* A function taking a function as an argument */
double Function1( Class2Func f2, double val )
{
    return f2(val);
}
 
/*A function returning a function */
Class2Func WhichFunc( int idx)
{
   return (idx < 4) ? &functionA : &functionB;
}
 
/* A list of functions */
Class2Func funcListA[] = {&functionA, &sin, &cos, &tan };
Class2Func funcListB[] = {&functionB, &asin, &acos, &atan };
 
/* Composing Functions */
double InvokeComposed( Class2Func f1, Class2Func f2, double val )
{
   return f1(f2(val));
}
 
typedef struct sComposition {
   Class2Func f1;
   Class2Func f2;
} *Composition;
 
Composition Compose( Class2Func f1, Class2Func f2)
{
   Composition comp = malloc(sizeof(struct sComposition));
   comp->f1 = f1;
   comp->f2 = f2;
   return comp;
}
 
double CallComposed( Composition comp, double val )
{
    return comp->f1( comp->f2(val) );
}
/** * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
int main(int argc, char *argv[])
{
   int ix;
   Composition c;
 
   printf("Function1(functionA, 3.0) = %f\n", Function1(WhichFunc(0), 3.0));
 
   for (ix=0; ix<4; ix++) {
       c = Compose(funcListA[ix], funcListB[ix]);
       printf("Compostion %d(0.9) = %f\n", ix, CallComposed(c, 0.9));
   }
 
   return 0;
}


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

typedef double (*f_dbl)(double);
#define TAGF (f_dbl)0xdeadbeef
#define TAGG (f_dbl)0xbaddecaf

double dummy(double x)
{
	f_dbl f = TAGF;
	f_dbl g = TAGG;
	return f(g(x));
}

f_dbl composite(f_dbl f, f_dbl g)
{
	size_t len = (void*)composite - (void*)dummy;
	f_dbl ret = malloc(len);
	char *ptr;
	memcpy(ret, dummy, len);
	for (ptr = (char*)ret; ptr < (char*)ret + len - sizeof(f_dbl); ptr++) {
		if (*(f_dbl*)ptr == TAGF)      *(f_dbl*)ptr = f;
		else if (*(f_dbl*)ptr == TAGG) *(f_dbl*)ptr = g;
	}
	return ret;
}

double cube(double x)
{
	return x * x * x;
}

/* uncomment next line if your math.h doesn't have cbrt() */
/* double cbrt(double x) { return pow(x, 1/3.); } */

int main()
{
	int i;
	double x;

	f_dbl A[3] = { cube, exp, sin };
	f_dbl B[3] = { cbrt, log, asin}; /* not sure about availablity of cbrt() */
	f_dbl C[3];

	for (i = 0; i < 3; i++)
		C[i] = composite(A[i], B[i]);

	for (i = 0; i < 3; i++) {
		for (x = .2; x <= 1; x += .2)
			printf("C%d(%g) = %g\n", i, x, C[i](x));
		printf("\n");
	}
	return 0;
}


C0(0.2) = 0.2
C0(0.4) = 0.4
C0(0.6) = 0.6
C0(0.8) = 0.8
C0(1) = 1

C1(0.2) = 0.2
C1(0.4) = 0.4
C1(0.6) = 0.6
C1(0.8) = 0.8
C1(1) = 1

C2(0.2) = 0.2
C2(0.4) = 0.4
C2(0.6) = 0.6
C2(0.8) = 0.8
C2(1) = 1


  

You may also check:How to resolve the algorithm Chinese remainder theorem step by step in the PARI/GP programming language
You may also check:How to resolve the algorithm Comma quibbling step by step in the Objeck programming language
You may also check:How to resolve the algorithm Paraffins step by step in the Kotlin programming language
You may also check:How to resolve the algorithm Call a foreign-language function step by step in the V (Vlang) programming language
You may also check:How to resolve the algorithm Case-sensitivity of identifiers step by step in the Raku programming language