Created
December 2, 2020 07:34
-
-
Save dasbluehole/893edc521b657c6904b4fa72f51f65c5 to your computer and use it in GitHub Desktop.
Simple Complex number and operators implementations. It also calculates nth roots of any number. See the main() function.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* simplex.c | |
* | |
* Copyright(C) 2020 Ashok Shankar Das <ashok.s.das@gmail.com> | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
* MA 02110-1301, USA. | |
* | |
* | |
*/ | |
/* !Info: | |
* Simplex is a set of routines for handling complex numbers | |
* these routines may not be very optimal but definitely workable. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#include <string.h> | |
// datatype defination to store the complex number | |
// x+jy has real part x and imaginary part +y | |
// so x is stored in .real and +y is stored in .imag field | |
// of the structure | |
typedef struct Complex | |
{ | |
double real, | |
imag; | |
}Complex; | |
// datatype to store the polar form of complex number | |
// r*cis(theta) | |
// r is magnitude sqrt(x^2+y^2) | |
// theta is angle of the radius vector to x-axis in | |
// CCw direction expressed in radians | |
typedef struct polar | |
{ | |
double radius, | |
theta; | |
}Cpolar; | |
/* !f gets real part of a complex number | |
* !i Complex | |
* !o double | |
*/ | |
double get_real(Complex c) | |
{ | |
return(c.real); | |
} | |
/* !f gets imaginary part of a complex number | |
* !i Complex | |
* !o double | |
*/ | |
double get_imag(Complex c) | |
{ | |
return(c.imag); | |
} | |
/* !f sets real part of a complex number | |
* !i pointer to Complex , double | |
* !o nothing | |
*/ | |
void set_real(Complex *c, double r) | |
{ | |
c->real = r; | |
} | |
/* !f sets imaginary part of a complex number | |
* !i pointer to Complex , double | |
* !o nothing | |
*/ | |
void set_imag(Complex *c, double img) | |
{ | |
c->imag = img; | |
} | |
/* !f makes a complex number | |
* !f accepts real part and imaginary part as double | |
* !i r double , i double | |
* !o Complex | |
*/ | |
Complex mk_complex(double r, double im) | |
{ | |
Complex z; | |
set_real(&z,r); | |
set_imag(&z,im); | |
return(z); | |
} | |
/* !f prints a complex number | |
* !i Complex | |
* !o nothing | |
*/ | |
void print_complex(Complex c) | |
{ | |
char sgn = '+'; | |
double r,im; | |
r=get_real(c); | |
im=get_imag(c); | |
if(im<0.0) | |
{ | |
sgn = '-'; | |
im = -1*im; | |
} | |
printf("%lf%cj%lf\n",r,sgn,im); | |
} | |
/* !f converts a complex number to string in x+jy form | |
* !i Complex, pre allocated char buffer | |
* !o nothing | |
*/ | |
void complex_to_str(Complex c,char *str) | |
{ | |
char sgn = '+'; | |
double r,im; | |
r=get_real(c); | |
im=get_imag(c); | |
if(im<0.0) | |
{ | |
sgn = '-'; | |
im = -1*im; | |
} | |
sprintf(str,"%lf%cj%lf",r,sgn,im); | |
} | |
/* !f converts a string in "x+jy" form to Complex | |
* !i string in "x+iy" format | |
* !o Complex | |
*/ | |
Complex string_to_complex(char *s) | |
{ | |
Complex zc; | |
char r_str[15]="0"; | |
char i_str[15]="0"; | |
char sgn='\0'; | |
if(strchr(s,'j')) | |
{ | |
int index=strchr(s,'j')-s; | |
strncpy(r_str,s,index-1); | |
strcpy(i_str,s+index+1); | |
sgn = *(s+index-1); | |
} | |
set_real(&zc,atof(r_str)); | |
if(sgn=='-') | |
{ | |
set_imag(&zc,-1*atof(i_str)); | |
} | |
else | |
set_imag(&zc,atof(i_str)); | |
return(zc); | |
} | |
// arith ops | |
/* !f adds 2 complex numbers | |
* !i Complex, Complex | |
* !o Complex | |
*/ | |
Complex Cadd(Complex c1, Complex c2) | |
{ | |
Complex z; | |
set_real(&z,get_real(c1)+get_real(c2)); | |
set_imag(&z,get_imag(c1)+get_imag(c2)); | |
return(z); | |
} | |
/* !f subtracts 2 complex numbers | |
* !i Complex, Complex | |
* !o Complex | |
*/ | |
Complex Csub(Complex c1, Complex c2) | |
{ | |
Complex z; | |
set_real(&z,get_real(c1)-get_real(c2)); | |
set_imag(&z,get_imag(c1)-get_imag(c2)); | |
return(z); | |
} | |
/* !f conjugate of a complex numbers | |
* !i Complex | |
* !o Complex | |
*/ | |
Complex Cconjugate(Complex c) | |
{ | |
Complex z; | |
set_real(&z,get_real(c)); | |
set_imag(&z,-1*get_imag(c)); | |
return(z); | |
} | |
/* !f multiplies 2 complex numbers | |
* !i Complex, Complex | |
* !o Complex | |
*/ | |
Complex Cmul(Complex c1, Complex c2) | |
{ | |
Complex z; | |
double rp1,ip1,rp2,ip2; | |
double r,i; | |
rp1=get_real(c1); | |
ip1=get_imag(c1); | |
rp2=get_real(c2); | |
ip2=get_imag(c2); | |
r = rp1*rp2-ip1*ip2; | |
i = rp1*ip2+rp2*ip1; | |
set_real(&z,r); | |
set_imag(&z,i); | |
return (z); | |
} | |
/* !f reciprocal of a complex numbers | |
* !i Complex | |
* !o Complex | |
*/ | |
Complex Creciprocal(Complex c) | |
{ | |
Complex z,cj; | |
double r,i,t; | |
r = get_real(c); | |
i = get_imag(c); | |
t = r*r+i*i; | |
cj = Cconjugate(c); | |
set_real(&z,get_real(cj)/t); | |
set_imag(&z,get_imag(cj)/t); | |
return(z); | |
} | |
/* !f devides a Complex with second Complex | |
* !i Complex, Complex | |
* !o Complex | |
*/ | |
Complex Cdiv(Complex c1, Complex c2) | |
{ | |
Complex z; | |
z = Creciprocal(c2); | |
z = Cmul(c1,z); | |
return(z); | |
} | |
/* !f magnitude of a complex numbers | |
* !i Complex | |
* !o double | |
*/ | |
double Cmod(Complex c) | |
{ | |
double m; | |
double r,i; | |
r = get_real(c); | |
i = get_imag(c); | |
m = sqrt(r*r+i*i); | |
return(m); | |
} | |
/* !f square root of a complex numbers | |
* !i Complex | |
* !o Complex | |
*/ | |
Complex Csqrt(Complex c) | |
{ | |
double r,i,sgn=1; | |
r = get_real(c); | |
i = get_imag(c); | |
Complex z; | |
if(i == 0) | |
{ | |
z = mk_complex(sqrt(r),0); | |
return(z); | |
} | |
double m; | |
m=sqrt(r*r+i*i); | |
if(i<0) | |
sgn=-1; | |
z = mk_complex(sqrt((m+r)/2),sgn*(sqrt((m-r)/2))); | |
return (z); | |
} | |
// polar co-ordinate helper function | |
/* !f gets radius vector from polar structure | |
* !i Cpolar | |
* !o double | |
*/ | |
double get_radiusv(Cpolar p) | |
{ | |
return (p.radius); | |
} | |
/* !f sets radius vector from polar structure | |
* !i pointer to Cpolar, double | |
* !o nothing | |
*/ | |
void set_radiusv(Cpolar *p,double rad) | |
{ | |
p->radius = rad; | |
} | |
/* !f gets angle of radius vector from polar structure | |
* !i Cpolar | |
* !o double (radian) | |
*/ | |
double get_theta(Cpolar p) | |
{ | |
return (p.theta); | |
} | |
/* !f sets angle of radius vector | |
* !i pointer to Cpolar, double | |
* !o nothing | |
*/ | |
void set_theta(Cpolar *p, double theta) | |
{ | |
p->theta = theta; | |
} | |
/* !f Complex form to polar form | |
* !i Complex | |
* !o Cpolar | |
*/ | |
Cpolar complex_to_polar(Complex c) | |
{ | |
Cpolar p; | |
double x,y; | |
x = get_real(c); | |
y = get_imag(c); | |
double mag = sqrt(x*x+y*y); | |
double ang = atan2(y,x); | |
set_radiusv(&p, mag); | |
set_theta(&p, ang); | |
return(p); | |
} | |
/* !f polar form to Complex form | |
* !i Complex | |
* !o Cpolar | |
*/ | |
Complex polar_to_complex(Cpolar p) | |
{ | |
Complex z; | |
double x,y; | |
double mag,th; | |
mag = get_radiusv(p); | |
th = get_theta(p); | |
x = mag * cos(th); | |
y = mag * sin(th); | |
set_real(&z,x); | |
set_imag(&z,y); | |
return(z); | |
} | |
/* !f Raises a Complex to a integral power | |
* !i Complex, Integer | |
* !o Complex | |
*/ | |
Complex Cnpow(Complex c, int n) | |
{ | |
// x+iy can be written as r(cos(theta)+i*Sin(theta)) => r*e^(i*(theta)) | |
// hence (x+iy)^n = (r*e^(i*(theta)))^n | |
// =(r^n)*e^(i*n*theta) = (r^n)*(cos(n*theta)+i*sin(n*theta)) | |
// now we can convert it back to cartesian format | |
Cpolar p; | |
double rn,nt; | |
p = complex_to_polar(c); | |
rn = pow(get_radiusv(p),n); | |
nt = get_theta(p)*n; | |
double x, y; | |
x = rn * cos(nt); | |
y = rn * sin(nt); | |
Complex z = mk_complex(x,y); | |
return(z); | |
} | |
/* !f finds n number of nth roots of a Complex number | |
* !i Complex, Integer, pre allocated array of Complex | |
* !o nothing | |
*/ | |
void Cnroot(Complex c, int n, Complex *root) | |
{ | |
Cpolar p = complex_to_polar(c); | |
double m = get_radiusv(p); | |
double th = get_theta(p); | |
for(int i=0; i< n; i++) | |
{ | |
double x = pow(m,1.0/n)*(cos((th+2*M_PI*i)/n)); | |
double y = pow(m,1.0/n)*(sin((th+2*M_PI*i)/n)); | |
root[i] = mk_complex(x,y); | |
} | |
} | |
int main() | |
{ | |
Complex z; | |
set_real(&z,2); | |
set_imag(&z,3); | |
char st[30]; | |
print_complex(z); | |
complex_to_str(z,st); | |
printf("%s\n",st); | |
strcpy(st,"15.0-j20.0"); | |
printf("%s\n",st); | |
Complex z1 = string_to_complex(st); | |
print_complex(z1); | |
complex_to_str(z1,st); | |
printf("%s\n",st); | |
set_real(&z1,-20.3); | |
set_imag(&z1,-33.543); | |
print_complex(z1); | |
complex_to_str(z1,st); | |
printf("%s\n",st); | |
Complex z2=mk_complex(3,5); | |
Complex z3=mk_complex(4,-3); | |
print_complex(z2); | |
print_complex(z3); | |
Complex z4 = Cadd(z2,z3); | |
print_complex(z4); | |
Complex z5=mk_complex(3,2); | |
Complex z6=mk_complex(1,7); | |
Complex z7=Cmul(z5,z6); | |
print_complex(z7); | |
Complex z8 = mk_complex(1,1); | |
z8 = Cmul(z8,z8); | |
print_complex(z8); | |
Complex z9 = mk_complex(2,3); | |
Complex z10= mk_complex(4,-5); | |
Complex z11 = Cdiv(z9,z10); | |
print_complex(z11); | |
z10 = Creciprocal(z10); | |
z11 = Cmul(z9,z10); | |
print_complex(z11); | |
Complex z12 = mk_complex(8,-6); | |
Complex z13 = Csqrt(z12); | |
print_complex(z13); | |
Complex z14 = Cnpow(z13,2); | |
print_complex(z14); | |
Complex z15[30]; | |
z14 = mk_complex(1,0); | |
Cnroot(z14,4,z15); | |
print_complex(z15[0]); | |
print_complex(z15[1]); | |
print_complex(z15[2]); | |
print_complex(z15[3]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment