code: mafs

ref: b5d191e8cfa4fac05a02ea309df2541a2652ff23
dir: /tag.c/

View raw version
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"

static u64
addu64ov(u64 a, u64 b)
{
	u64 r = a + b;

	if (r < a || r < b)
		return 0;
	return r;
}

static u64
mulu64ov(u64 a, u64 b)
{
	u64 r = a * b;

	if (a != 0 && r/a != b || r < a || r < b)
		return 0;
	return r;
}

/* could use muluvlongov() here but it does not add any value for us
	raise base to n-th power; n >= 0
 */
u64
power(u64 base, int n)
{
	int i;
	u64 v;

	v = 1;
	for(i = 1; i <= n; i++)
		v = v*base;
	return v;
}

/* Each u64 address in this indirect block links to n Tdata/Tdentry blocks */
u64
nperindunit(u16 tag)
{
	if(tag < Tind0 || tag > Tmaxind+1)
		return 0;

	return power(Nindperblock, tag-Tind0);
}

/*
 * compute BUFSIZE*(Ndblock+INDPERBUF+INDPERBUF²+INDPERBUF³+INDPERBUF⁴ .. upto ^Niblock)
 * while watching for overflow; in that case, return 0.
 */
/* extern double pow(double x, double y); *//* return x ^ y (exponentiation) */
/* Each u64 address in the indirect block links to n Tdata/Tdentry blocks */
/* Each u64 address in the indirect block links to n Tdata/Tdentry blocks */
u64
nperiblock(u16 tag)
{
	return nperindunit(tag+1);
}

/* get the Tindn tag of the block that a reli belongs to */
u8
rel2tind(u64 reli)
{
	u64 maxfortag, tag, i;

	if(reli < Ndblock){
		panic("should not be here");
	}
	reli -= Ndblock;

	for(tag = Tind0, i = reli; tag <= Tmaxind; tag++){
		maxfortag = nperiblock(tag);
		if(i < maxfortag)
			break;
		i -= maxfortag;
	}
	return tag;
}

/* blocks above this index have this tag
	For example,
		Tind0 starts from a reli >= 24
		Tind1 starts from a reli >= 74
		Tind2 starts from a reli >= 3100
 */
u64
tagstartreli(u8 tag)
{
	if(tag == Tind0)
		return Ndblock;
	else if(tag == Tind1)
		return Ndblock+Nindperblock;
	return nperiblock(tag-1)+tagstartreli(tag-1);
}

u64
maxreli(u8 tag)
{
	return tagstartreli(tag+1)-1;
}

u64
maxblocks(u8 tag)
{
	return maxreli(tag)+1;
}