Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
C
COMP2215 Coursework
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
wjg1g21
COMP2215 Coursework
Commits
aeb22d50
Commit
aeb22d50
authored
2 years ago
by
William Grant
Browse files
Options
Downloads
Patches
Plain Diff
fixmath (unfinished)
parent
b11bd2c2
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
fixmath/fixmath.c
+120
-0
120 additions, 0 deletions
fixmath/fixmath.c
fixmath/fixmath.h
+72
-0
72 additions, 0 deletions
fixmath/fixmath.h
with
192 additions
and
0 deletions
fixmath/fixmath.c
0 → 100644
+
120
−
0
View file @
aeb22d50
#include
"fixmath.h"
#include
<stdint>
fix_t
fix_emul
(
fix_t
x
,
fix_t
y
)
{
uint64_t
big_x
=
x
.
raw
;
uint64_t
big_y
=
y
.
raw
;
return
(
fix_t
)
{
.
raw
=
(
big_x
*
big_y
)
>>
16
}
}
fix_t
fix_ediv
(
fix_t
x
,
fix_t
y
)
{
uint64_t
big_x
=
x
.
raw
;
uint64_t
big_y
=
y
.
raw
;
return
(
fix_t
)
{
.
raw
=
(
big_x
<<
16
)
/
big_y
}
}
fix_t
fix_esqrt
(
fix_t
x
)
{
// special case sqrt(0) = 0
if
(
x
.
raw
==
0
)
{
return
x
;
}
// calculate an initial estimate for x
// use __builtin_clz to count leading zeros
// highest set bit position is 31 - result
int
hsb_pos
=
31
-
__builtin_clz
(
x
.
raw
);
// shift until in range [0.5, 2) (get distance from hsb and desired value)
int
shift
=
msb_pos
-
16
;
if
(
shift
%
2
!=
0
)
{
++
shift
;
}
fix_t
a
;
if
(
shift
>=
0
)
{
a
=
{
.
raw
=
x
.
raw
>>
shift
};
}
else
{
a
=
{
.
raw
=
x
.
raw
<<
-
shift
};
}
int
n
=
shift
/
2
;
// initial estimate is (0.5 + 0.5*a) * 2^n
fix_t
y
=
{
.
raw
=
fix_eadd
(
half
,
fix_emul
(
half
,
a
)).
raw
<<
n
};
// peform a few iterations of newton's method
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
y
=
fix_ediv
(
fix_eadd
(
y
,
fix_ediv
(
x
,
y
)),
half
);
}
return
y
;
}
void
fix_eto_string
(
fix_t
x
,
char
[]
buf
)
{
uint32_t
raw
=
x
.
raw
;
int
index
=
-
1
;
// if the number is negative then invert it and add a '-'
if
(
raw
&
(
1
<<
31
))
{
buf
[
++
index
]
=
'-'
;
raw
=
-
raw
;
}
//
while
(
raw
!=
0
)
{
uint32_t
rem
=
raw
%
10
;
raw
/=
10
;
}
}
// TODO find a way to eliminate this repetition!
fix_unit_t
fix_umul
(
fix_unit_t
x
,
fix_unit_t
y
)
{
uint64_t
big_x
=
x
.
raw
;
uint64_t
big_y
=
y
.
raw
;
return
(
fix_unit_t
)
{
.
raw
=
(
big_x
*
big_y
)
>>
31
}
}
fix_unit_t
fix_udiv
(
fix_unit_t
x
,
fix_unit_t
y
)
{
uint64_t
big_x
=
x
.
raw
;
uint64_t
big_y
=
y
.
raw
;
return
(
fix_unit_t
)
{
.
raw
=
(
big_x
<<
31
)
/
big_y
}
}
fix_unit_t
fix_usqrt
(
fix_unit_t
x
)
{
// special case sqrt(0) = 0
if
(
x
.
raw
==
0
)
{
return
x
;
}
// calculate an initial estimate for x
// use __builtin_clz to count leading zeros
// highest set bit position is 31 - result
int
hsb_pos
=
31
-
__builtin_clz
(
x
.
raw
);
// shift until in range [0.5, 2) (get distance from hsb and desired value)
int
shift
=
msb_pos
-
31
;
if
(
shift
%
2
!=
0
)
{
++
shift
;
}
fix_t
a
;
if
(
shift
>=
0
)
{
a
=
{
.
raw
=
x
.
raw
>>
shift
};
}
else
{
a
=
{
.
raw
=
x
.
raw
<<
-
shift
};
}
int
n
=
shift
/
2
;
// initial estimate is (0.5 + 0.5*a) * 2^n
fix_t
y
=
{
.
raw
=
fix_uadd
(
half
,
fix_umul
(
half
,
a
)).
raw
<<
n
};
// peform a few iterations of newton's method
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
y
=
fix_udiv
(
fix_uadd
(
y
,
fix_udiv
(
x
,
y
)),
half
);
}
return
y
;
}
This diff is collapsed.
Click to expand it.
fixmath/fixmath.h
0 → 100644
+
72
−
0
View file @
aeb22d50
#pragma once
#include
<stdint>
// standard, even type (16.16) with range [-32768, 32768)
typedef
struct
{
uint32_t
raw
;
}
fix_t
;
// unit type (1.31) with range [-1, 1)
typedef
struct
{
uint32_t
raw
;
}
fix_unit_t
;
// fix_t functions
static
inline
fix_t
fix_eadd
(
fix_t
x
,
fix_t
y
)
{
return
(
fix_t
)
{
.
raw
=
x
.
raw
+
y
.
raw
};
}
static
inline
fix_t
fix_esub
(
fix_t
x
,
fix_t
y
)
{
return
(
fix_t
)
{
.
raw
=
x
.
raw
-
y
.
raw
};
}
static
inline
fix_t
fix_eneg
(
fix_t
x
)
{
return
(
fix_t
)
{
.
raw
=
-
x
.
raw
};
}
fix_t
fix_emul
(
fix_t
x
,
fix_t
y
);
fix_t
fix_ediv
(
fix_t
x
,
fix_t
y
);
fix_t
fix_esqrt
(
fix_t
x
);
static
inline
fix_t
fix_efrom_int
(
int
x
)
{
return
(
fix_t
)
{
.
raw
=
x
<<
16
}
}
void
fix_eto_string
(
fix_t
x
,
char
[]
buf
);
// fix_unit_t functions
static
inline
fix_unit_t
fix_uadd
(
fix_unit_t
x
,
fix_unit_t
y
)
{
return
(
fix_unit_t
)
{
.
raw
=
x
.
raw
+
y
.
raw
};
}
static
inline
fix_unit_t
fix_usub
(
fix_unit_t
x
,
fix_unit_t
y
)
{
return
(
fix_unit_t
)
{
.
raw
=
x
.
raw
-
y
.
raw
};
}
static
inline
fix_unit_t
fix_eneg
(
fix_t
x
)
{
return
(
fix_unit_t
)
{
.
raw
=
-
x
.
raw
};
}
fix_unit_t
fix_umul
(
fix_unit_t
x
,
fix_unit_t
y
);
fix_unit_t
fix_udiv
(
fix_unit_t
x
,
fix_unit_t
y
);
fix_unit_t
fix_usqrt
(
fix_unit_t
x
);
static
inline
fix_unit_t
fix_ufrom_reciprocal
(
int
x
)
{
return
(
fix_unit_t
)
{
.
raw
=
(
1
<<
31
)
/
x
};
}
void
fix_uto_string
(
fix_t
x
,
char
[]
buf
);
// generic macros
# define fix_add(x, y) _Generic(x, fix_t: fix_eadd, fix_unit_t: fix_uadd)(x, y)
# define fix_sub(x, y) _Generic(x, fix_t: fix_esub, fix_unit_t: fix_usub)(x, y)
# define fix_mul(x, y) _Generic(x, fix_t: fix_emul, fix_unit_t: fix_umul)(x, y)
# define fix_div(x, y) _Generic(x, fix_t: fix_ediv, fix_unit_t: fix_udiv)(x, y)
# define fix_sqrt(x) _Generic(x, fix_t: fix_esqrt, fix_unit_t: fix_usqrt)(x)
# define fix_to_string(x, buf) _Generic(x, fix_t: fix_eto_string, fix_unit_t: fix_uto_string)(x, buf)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment