Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 104 additions & 59 deletions math/fxp.act
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ namespace math {
chp {
[ v >= 0.0 -> self := int(v * (1 << B) + 0.5)
[] else -> self := int(-v * (1 << B) + 0.5);
self := (1 << (A+B)) - self
self := (1 << (A+B)) - self
]
}
}
Expand Down Expand Up @@ -121,7 +121,7 @@ namespace math {
function le(int<A+B> x, y) : bool
{
chp {
[ x{A+B-1} = 1 & y{A+B-1} = 0 -> self := true
[ x{A+B-1} = 1 & y{A+B-1} = 0 -> self := true
[] y{A+B-1} = 1 & x{A+B-1} = 0 -> self := false
[] else -> self := (x <= y)
]
Expand All @@ -146,16 +146,31 @@ namespace math {
}
}

template<pint N>
function round(int<1> lsb; int<N> off) : int<1> {
chp {
// trunc
[ FXP_ROUNDING_MODE = 0 -> self := 0
[] FXP_ROUNDING_MODE = 1 -> // half to even
self := (off{N-1} = 0) | (off = int(1 << (N - 1), N) & lsb = 0) ? 0 : 1
[] else -> assert(0)
]
}
}

export
template<pint A,B>
function mults (int<A+B> x, y) : int<A+B>
{
bool sx, sy;
int<2 * A + 2 * B> r;

chp {
[ x{A+B-1} = 1 -> sx+; x := ~x + 1 [] else -> sx- ];
[ y{A+B-1} = 1 -> sy+; y := ~y + 1 [] else -> sy- ];
self := (x * y) >> B;
[ sx != sy -> self := ~self + 1 [] else -> skip ]
[ x{A+B-1} = 1 -> sx+; x := ~x + 1 [] else -> sx- ];
[ y{A+B-1} = 1 -> sy+; y := ~y + 1 [] else -> sy- ];
r := (x * y);
self := (r >> B) + round<B>(r{B}, r{B-1..0});
[ sx != sy -> self := ~self + 1 [] else -> skip ]
}
}

Expand All @@ -167,20 +182,20 @@ namespace math {
self := (x * y) >> B
}
}

export
template<pint A,B>
function divs (int<A+B> x, y) : int<A+B>
{
bool sx, sy;
chp {
[ x{A+B-1} = 1 -> sx+; x := ~x + 1 [] else -> sx- ];
[ y{A+B-1} = 1 -> sy+; y := ~y + 1 [] else -> sy- ];
[ x{A+B-1} = 1 -> sx+; x := ~x + 1 [] else -> sx- ];
[ y{A+B-1} = 1 -> sy+; y := ~y + 1 [] else -> sy- ];
self := (x << B) / y;
[ sx != sy -> self := ~self + 1 [] else -> skip ]
[ sx != sy -> self := ~self + 1 [] else -> skip ]
}
}

export
template<pint A,B>
function divu (int<A+B> x, y) : int<A+B>
Expand All @@ -198,73 +213,72 @@ namespace math {
self := ~x + 1
}
}

}

export
template <pint A, B>
template <pint A,B>
deftype fixpoint(int<A+B> x)
{
methods {
function plus(fixpoint<A,B> rhs) : fixpoint<A,B>
{
chp {
self.x := fxp::add<A,B>(x,rhs.x)
}
chp {
self.x := fxp::add<A,B>(x,rhs.x)
}
}
function minus(fixpoint<A,B> rhs) : fixpoint<A,B>
{
chp {
self.x := fxp::sub<A,B>(x,rhs.x)
}
chp {
self.x := fxp::sub<A,B>(x,rhs.x)
}
}
function mult(fixpoint<A,B> rhs) : fixpoint<A,B>
{
chp {
self.x := fxp::mults<A,B>(x,rhs.x)
}
chp {
self.x := fxp::mults<A,B>(x,rhs.x)
}
}
function div(fixpoint<A,B> rhs) : fixpoint<A,B>
{
chp {
self.x := fxp::divs<A,B>(x,rhs.x)
}
chp {
self.x := fxp::divs<A,B>(x,rhs.x)
}
}
function uminus() : fixpoint<A,B>
{
chp {
self.x := fxp::uminus<A,B>(x)
}
chp {
self.x := fxp::uminus<A,B>(x)
}
}
function le(fixpoint<A,B> rhs) : bool
{
chp {
self := fxp::le<A,B>(x, rhs.x)
}
chp {
self := fxp::le<A,B>(x, rhs.x)
}
}
function lt(fixpoint<A,B> rhs) : bool
{
chp {
self := (x != rhs.x) & fxp::le<A,B>(x, rhs.x)
}
chp {
self := (x != rhs.x) & fxp::le<A,B>(x, rhs.x)
}
}
function ne(fixpoint<A,B> rhs) : bool
{
chp {
self := (x != rhs.x)
}
chp {
self := (x != rhs.x)
}
}
function ge(fixpoint<A,B> rhs) : bool
{
chp {
self := fxp::le<A,B>(rhs.x, x)
}
chp {
self := fxp::le<A,B>(rhs.x, x)
}
}
function gt(fixpoint<A,B> rhs) : bool
{
chp {
self := (x != rhs.x) & fxp::le<A,B>(rhs.x, x)
}
chp {
self := (x != rhs.x) & fxp::le<A,B>(rhs.x, x)
}
}

macro set(int<A+B> v)
Expand All @@ -282,46 +296,77 @@ namespace math {
function positive() : bool
{
chp {
self := fxp::positive<A, B>(x)
self := fxp::positive<A,B>(x)
}
}

function negative() : bool
{
chp {
self := fxp::negative<A, B>(x)
self := fxp::negative<A,B>(x)
}
}

function zero() : bool {
chp {
self := fxp::zero<A, B>(x)
self := fxp::zero<A,B>(x)
}
}

function const(preal v) : pint
{
chp {
self := fxp::conv_to_fxp(A,B,v)
}
chp {
self := fxp::conv_to_fxp(A,B,v)
}
}

macro log()
{
log_st("");
[ x{A+B-1} = 1 -> log_p("-", int(~x+1,A+B)>>B)
[] else -> log_p("+", x >> B)
];
log_p (".{", (x{A+B-1} = 1 ? int(~x+1,A+B) : x) & int((1 << B)-1,B), "/", (1 << B), "}");
log_nl("")
log_st("");
[ x{A+B-1} = 1 -> log_p("-", int(~x+1, A+B)>>B)
[] else -> log_p("+", x >> B)
];
log_p (".{", (x{A+B-1} = 1 ? int(~x+1, A+B) : x) & int((1 << B)-1, B), "/", (1 << B), "}");
log_nl("")
}

macro log_p()
{
[ x{A+B-1} = 1 -> log_p("-", int(~x+1,A+B)>>B)
[] else -> log_p("+", x >> B)
];
log_p (".{", (x{A+B-1} = 1 ? int(~x+1,A+B) : x) & int((1 << B)-1,B), "/", (1 << B), "}")
[ x{A+B-1} = 1 -> log_p("-", int(~x+1, A+B)>>B)
[] else -> log_p("+", x >> B)
];
log_p (".{", (x{A+B-1} = 1 ? int(~x+1, A+B) : x) & int((1 << B)-1, B), "/", (1 << B), "}")
}
}
}

export namespace fxp {
export
template<pint A_FROM,B_FROM,A_TO,B_TO>
function sdowncast(fixpoint<A_FROM,B_FROM> a) : fixpoint<A_TO,B_TO> {
{A_FROM > A_TO};
{B_FROM > B_TO};

int<1> rnd;

chp {
rnd := round<B_FROM - B_TO>(a.x{B_FROM - B_TO}, a.x{B_FROM - B_TO - 1..0});
self.x := {a.x{(A_TO + B_FROM - 1)..B_FROM}, a.x{B_FROM-1..(B_FROM - B_TO)}} + rnd
}
}

export
template<pint A_FROM,B_FROM,A_TO,B_TO>
function supcast(fixpoint<A_FROM,B_FROM> a) : fixpoint<A_TO,B_TO> {
{A_FROM < A_TO};
{B_FROM < B_TO};

chp {
self.x := a.x{(A_FROM + B_FROM - 1)..B_FROM} << B_TO | a.x{(B_FROM - 1)..0} << (B_TO - B_FROM);
[ a.x{A_FROM + B_FROM - 1} = 0 -> skip
// sign extend
[] else -> self.x := self.x | (~int(0, A_TO - A_FROM) << (A_FROM + B_TO))
]
}
}
}
Expand Down