-- --############################################################### --# FDData, a base information medium for the SOME project: # --############################################################### -- John Ringland 2005/08/27 include SOME_Utilities.e -- FDBits global type FDBits(object b) return isNum(b) and b > 0 end type -- Resolution = Limit/delta = 2^FDBits - 1 global type FDRes(object r) return isNum(r) and r >= 0 end type -- FDIndex = squiggly delta -- maximum value approximately 2^48 = 10^14 global type FDIndex(object v) return isNum(v) and v >= -1 and v-floor(v)=0 -- v=-1 means null value and it is an integer end type -- FDDelta = triangle delta global type FDDelta(object d) return isNum(d) and d > 0 end type -- FDMin = 0, by default global type FDMin(object m) return isNum(m) end type -- FDMax = L, the limit global type FDMax(object l) return isNum(l) end type -- FDValue = FDMin + FDIndex*FDDelta global type FDValue(object v) return isNum(v) end type -- FDData = FDMin + FDIndex*FDDelta = FDMax - (FDRes - FDIndex)*FDDelta -- FDMax = FDmin + FDRes*FDDelta -- FDData = {FDIndex, FDDelta, FDMin, FDRes} -- first three are generally required, the last gives -- the maximum FDIndex and therefore FDMax and also FDBits. global type FDData(object v) return sequence(v) and length(v)=4 and FDIndex(v[1]) and FDDelta(v[2]) and FDMin(v[3]) and FDRes(v[4]) and v[1] <= v[4] and FDBits(log2(v[4]+1)) end type -- ####################################### -- # accessor functions for FDDatas: # -- ####################################### global constant FDIND_ = 1 global constant FDDEL_ = 2 global constant FDMIN_ = 3 global constant FDRES_ = 4 global function fdCreate(FDBits b, FDMin min, FDMax max, FDIndex val) FDRes r FDDelta d FDData v r = power(2,b)-1 d = (max - min)/r v = {val, d, min, r} return v end function global function fdIsNull(FDData v) return v[FDIND_]=-1 end function global function fdIndex(FDData v) return v[FDIND_] end function -- returns the FDValue represented by the FDData global function fdGet(FDData v) if fdIsNull(v) then error("Error: in function fdGet. Cannot evaluate a null FDData\n") return nan end if return v[FDMIN_] + v[FDIND_]*v[FDDEL_] end function global function fdSet(FDData v, atom val) object fdv if FDValue(val) then fdv = {floor((val-v[FDMIN_])/v[FDDEL_])} & v[FDDEL_..FDRES_] if FDData(fdv) then return fdv end if end if return {-1} & v[FDDEL_..FDRES_] -- a null FDData end function global function defaultFDV(atom val) if FDValue(val) then -- bits min max idx value return fdSet(fdCreate(60, -1024, 1023, 0), val) else return fdSet(fdCreate(60, -1024, 1023, 0), nan) -- a null FDData end if end function global constant fdZero = defaultFDV(0) global constant fdOne = defaultFDV(1) global constant fdMinusOne = defaultFDV(-1) global constant fdNan = {-1} & fdZero[FDDEL_..FDRES_] -- note: -- v = fdAdd(v, v1, v2) -- is equivalent to -- v = fdSet(v, fdGet(v1) + fdGet(v2)) global function fdAdd(FDData v, FDData v1, FDData v2) return fdSet(v, fdGet(v1) + fdGet(v2)) end function global function fdSubtract(FDData v, FDData v1, FDData v2) return fdSet(v, fdGet(v1) - fdGet(v2)) end function global function fdMultiply(FDData v, FDData v1, FDData v2) return fdSet(v, fdGet(v1) * fdGet(v2)) end function global function fdDivide(FDData v, FDData v1, FDData v2) object val val = fdGet(v2) if val = 0 then error("Error: In fdDivide. Cannot divide by zero.\n") return {-1} & v[FDDEL_..FDRES_] -- a null FDData end if return fdSet(v, fdGet(v1) / val) end function -- d should be an integer but the integer range is too small global function fdInc(FDData v, atom d) object fdv if not fdIsNull(v) then -- a Null FDData cannot be incremented fdv = {roundoff(v[FDIND_]+d)} & v[FDDEL_..FDRES_] if FDData(fdv) then return fdv end if end if return {-1} & v[FDDEL_..FDRES_] -- a null FDData end function global procedure FDdisp(FDData v) -- if not fdIsNull(v) then ?v & fdGet(v) -- end if end procedure procedure testFDData() FDData v1, v2, v3--, v4, v5, v6 atom b, min, max b = 64 min = -1000 max = 1000 v1 = fdCreate(b, min, max, power(2,b-1)) v2 = fdCreate(b, min, max, power(2,b-1)) v3 = fdCreate(b, min, max, 0) for i = 1 to 200 do puts(1,"#### Another round ####\n") --trace(1) FDdisp(v1) FDdisp(v2) FDdisp(fdAdd(v3,v1,v2)) -- ? fdGet(v1) + fdGet(v2) FDdisp(fdSubtract(v3,v1,v2)) -- ? fdGet(v1) - fdGet(v2) FDdisp(fdMultiply(v3,v1,v2)) -- ? fdGet(v1) * fdGet(v2) FDdisp(fdDivide(v3,v1,v2)) -- if fdGet(v2) != 0 then -- ? fdGet(v1) / fdGet(v2) -- else -- puts(1,"infinity\n") -- end if v1 = fdInc(v1,1e15) v2 = fdInc(v2,-1e15) end for end procedure -- there is constant entropy being produced -- and it is easy to get an overflow error. -- testFDData()