Skip to content

Instantly share code, notes, and snippets.

@AnastasiaDunbar
Last active October 2, 2019 08:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AnastasiaDunbar/99a8f90a8525322ae9c39fa503526a44 to your computer and use it in GitHub Desktop.
Save AnastasiaDunbar/99a8f90a8525322ae9c39fa503526a44 to your computer and use it in GitHub Desktop.
//Note: JavaScript bitwise operators can only handle 32 bits, and 31st bit is used as a sign bit (use `x>>>0` to unsign it).
//Note: `1<<x` is sometimes used like an alternative to `2**x` (or `Math.pow(2,x)`) here.
//sign , (exponent bit)*eb , (mantissa bit)*mb.
function customFloatSize(eb,mb){return eb+mb+1;}
function maximumFloatNumber(eb,mb){let e=1<<(((1<<eb)-2)-1);return e+(e*(1-(1/(1<<mb))));}
function fromCustomFloat(x,eb,mb){
let sign=(x>>>(eb+mb))&1?-1:1,
maxExp=(1<<eb)-1,
expBits=(x>>>mb)&maxExp,
mantissaMax=1<<mb,
mantissaBits=x&(mantissaMax-1);
if(expBits===maxExp){
return(mantissaBits!==0)?NaN:Infinity*sign;
}else{
return(expBits? //Is normal?
((1<<(expBits-1))*(mantissaBits+mantissaMax))/mantissaMax:
mantissaBits/mantissaMax
)*sign;
}
}
function toCustomFloat(x,eb,mb){
if(isNaN(x)){return(((1<<eb)-1)<<mb)|1;}
let sign=x<0?1<<(mb+eb):0;
if(sign){x*=-1;} //Make the value positive.
if(x===Infinity||x>=(1<<(((1<<eb)-1)-1))){return(((1<<eb)-1)<<mb)|sign;}
if(x<1){ //Subnormal.
let m=0;
return(x*(1<<mb))|sign; //TODO: Fix rounding.
}else{ //Normalized.
let e=Math.floor(Math.log2(x)+1), //TODO: Fix rounding.
b=1<<(e-1),
m=(x-b)/(b/(1<<mb)); //TODO: Fix rounding.
return(m&((1<<mb)-1))|((e&((1<<eb)-1))<<mb)|sign;
}
}
/*
Minifloat bit specification: 1 sign bit, 4 exponent bits (0-15) and 3 significand/mantissa bits (0-7); 0bSEEEEMMM.
var exponentBias=bitsInExponent=>Math.pow(2,bitsInExponent-1)-1,
mix=(x,y,a)=>(a*(y-x))+x;
For normalized numbers:
`mix(2**(x-1),2**x,y/z)` → `((y/z)*((2**x)-(2**(x-1))))+(2**(x-1))` → `((2**(x-1))*(y+z))/z` or `(2**(x-(Math.log2(z)+1)))*(y+z)`.
For minifloats:
`mix(2**(x-1),2**x,y/8)` → `(2**(x-4))*(y+8)`.
*/
function toMinifloat(x){return toCustomFloat(x,4,3);}
function fromMinifloat(x){return fromCustomFloat(x,4,3);}
//Test case.
[
// (SEEEEMMM)
[0b00000000,0],
[0b00000100,0.5],
[0b00001000,1],
[0b10001000,-1],
[0b00010000,2],
[0b00010010,2.5],
[0b00010100,3],
[0b00011111,7.5],
[0b01110000,8192],
[0b01110111,15360],
[0b01111000,Infinity],
[0b11111000,-Infinity],
[0b11111101,NaN]
].map(x=>`${x[0].toString(2).padStart(8,"0")}, ${x[1]}, ${fromMinifloat(x[0])}`).join("\n");
@AnastasiaDunbar
Copy link
Author

AnastasiaDunbar commented Oct 2, 2019

For more references:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment