Skip to content

Commit

Permalink
Add initial package for complex numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
BrentSeidel committed Aug 1, 2023
1 parent dfb32a0 commit 4346db2
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ A rough outline of what I plan is below. Obviously, this will be subject to cha
of these packages will be generic so that they can be used on different numerical types.

## Complex Numbers
In general, you should probably use the complex package in the Ada standard
numerics library. This is more of a practice run for me. The one difference
is that complex numbers are a tagged record so that object notation can be used
for some of the operations, if that's important to you.

## Integration

Expand Down
13 changes: 13 additions & 0 deletions numerical.gpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
with "..\BBS-Ada\bbs.gpr";

library project Numerical is

for Languages use ("Ada");
for Library_Name use "Numerical";
for Source_Dirs use ("src/**");
for Object_Dir use "obj";
for Library_Dir use "lib";
for Library_Kind use "Static";

end Numerical;

123 changes: 123 additions & 0 deletions src/complex/BBS-complex_real.adb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
with Ada.Numerics.Generic_Elementary_Functions;
package body BBS.complex_real is
package elem is new Ada.Numerics.Generic_Elementary_Functions(f);
--
-- Basic manipulations
--
function real(self : in complex) return f'Base is
begin
return self.r;
end;
--
function imaginary(self : in complex) return f'Base is
begin
return self.i;
end;
--
procedure set_cartisian(self : out complex; real, imag : f) is
begin
self.r := real;
self.i := imag;
end;
--
function conjugate(self : in complex) return complex is
begin
return (r => self.r, i => -(self.i));
end;
--
-- Basic operations
--
function "+" (Left, Right : complex) return complex is
begin
return (r => (Left.r + Right.r),
i => (Left.i + Right.i));
end;
--
function "-" (Left, Right : complex) return complex is
begin
return (r => (Left.r - Right.r),
i => (Left.i - Right.i));
end;
--
-- This is the standard process for multiplying complext numbers. There is
-- a method that only uses three multiplications, but four add/subtract.
-- For modern FPUs, there is probably no advantage, but if you are using a
-- software FPU, and a lot of complex multiplies, it might be worthwhile to
-- look it up and use it here.
--
function "*" (Left, Right : complex) return complex is
begin
return (r => (Left.r * Right.r) - (Left.i * Right.i),
i => (Left.r * Right.i) + (Left.i * Right.r));
end;
--
function "*" (Left : f; Right : complex) return complex is
begin
return (r => Right.r * Left, i => Right.i * Left);
end;
--
function "*" (Left : complex; Right : f) return complex is
begin
return (r => Left.r * Right, i => Left.i * Right);
end;
--
function "/" (Left, Right : complex) return complex is
conjsq : f := (Right.r * Right.r) + (Right.i * Right.i);
begin
return (r => ((Left.r * Right.r) + (Left.i * Right.i))/conjsq,
i => ((Left.r * Right.i) - (Left.i * Right.r))/conjsq);
end;
--
function "/" (Left : complex; Right : f) return complex is
begin
return (r => Left.r / Right, i => Left.i / Right);
end;
--
-- Polar related
--
procedure set_polar(self : out complex; mag, angle : f) is
begin
self.r := mag * elem.Cos(angle);
self.i := mag * elem.Sin(angle);
end;
--
function magnitude(self : in complex) return f'Base is
begin
return elem.Sqrt((self.r * self.r) + (self.i * self.i));
end;
--
function angle(self : in complex) return f'Base is
begin
return elem.Arctan(self.i, self.r);
end;
--
-- Comparisons
-- Note that complex numbers are not ordered so there is no comparison to
-- one being greater or less than another. These functions test for equality
-- within a tolerence.
--
-- Test if value's real and imaginary parts are with in the tolerence of the
-- test. This is effectively if value is within a square centered on self.
--
function near_sq(self : in complex; value : complex; tol : f) return Boolean is
begin
return (abs(self.r - value.r) < tol) and (abs(self.i - value.i) < tol);
end;
--
-- Test if value's distance from self is with in the tolerence. This is
-- effectively if value is within a circle centered on self.
--
function near_cir(self : in complex; value : complex; tol : f) return Boolean is
begin
return ;
end;
--
-- Additional functions
--
function exp(self : in complex) return complex is
t1 : f := elem.Exp(self.r);
begin
return (r => t1 * elem.Cos(self.i), i => t1 * elem.Sin(self.i));
end;
--
end BBS.complex_real;
66 changes: 66 additions & 0 deletions src/complex/BBS-complex_real.ads
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--
-- There already is a complex number package as part of Ada.Numerics. So, this
-- package isn't really needed. This is more of a practice run for me.
--
-- The one difference is that in this package, complex numbers are an object
-- so that object notation can be used in many case.
--
generic
type F is digits <>;
package BBS.complex_real is
type complex is tagged record
r : f'Base;
i : f'Base;
end record;
--
-- Basic manipulations
--
function real(self : in complex) return f'Base;
function imaginary(self : in complex) return f'Base;
procedure set_cartisian(self : out complex; real, imag : f);
function conjugate(self : in complex) return complex;
--
-- Basic arithmatic operations
--
function "+" (Left, Right : complex) return complex;
function "-" (Left, Right : complex) return complex;
function "*" (Left, Right : complex) return complex;
function "*" (Left : f; Right : complex) return complex;
function "*" (Left : complex; Right : f) return complex;
function "/" (Left, Right : complex) return complex;
function "/" (Left : complex; Right : f) return complex;
--
-- Polar related
--
procedure set_polar(self : out complex; mag, angle : f);
function magnitude(self : in complex) return f'Base;
function angle(self : in complex) return f'Base;
--
-- Comparisons
-- Note that complex numbers are not ordered so there is no comparison to
-- one being greater or less than another. These functions test for equality
-- within a tolerence.
--
-- Test if value's real and imaginary parts are with in the tolerence of the
-- test. This is effectively if value is within a square centered on self.
--
function near_sq(self : in complex; value : complex; tol : f) return Boolean;
--
-- Test if value's distance from self is with in the tolerence. This is
-- effectively if value is within a circle centered on self.
--
function near_cir(self : in complex; value : complex; tol : f) return Boolean;
--
-- Additional functions
--
function exp(self : in complex) return complex;
--
-- Constants
--
zero : constant complex := (r => 0.0, i => 0.0);
one : constant complex := (r => 1.0, i => 0.0);
j : constant complex := (r => 0.0, i => 1.0);
i : complex renames j;
private

end BBS.complex_real;

0 comments on commit 4346db2

Please sign in to comment.