You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was trying to make a Fibonacci calculator that was to use an Object Literal as a cache for the results but since the TypeScript configuration does not allow the any type, I am unable to define an Object Literal whose keys are any number from 0 to ~200. I wanted to know if there may be a way around this
So I tried using Map<i32,i32> but then now the compiler brings up different errors concerning the get method in Map. I am using TypeScript v 2.9.
Here's the code I implemented. Maybe you could let me know where I went wrong
let cache: Map<i32, i32> = new Map();
export function fib(num: i32): i32 {
if (!cache.has(num)) {
let a: i32 = 0,
b: i32 = 1,
tmp: i32;
for (let i = 0; i < num; i++) {
// Array destructuting presents an error so I must use a third variable for value swapping
tmp = a;
a = b;
b = tmp + b;
}
cache.set(num, a);
}
return cache.get(num);
}
By the way for huge input numbers you can use analytical fib implementation:
constSQRT5=Math.sqrt(5.0);constC1=Math.log((SQRT5+1.0)*0.5);constC2=Math.log((SQRT5-1.0)*0.5);// result is precise in range [0, 2^53-1]functionfib(n: f64): f64{if(n<=0)return0;vara=Math.exp(C1*n);varb=Math.exp(C2*n);returnMath.round((n&1 ? a+b : a-b)*(1.0/SQRT5));}
Well now it compiles for sure however now the JavaScript code fails to "recognize" the exported code as either functions or objects. This seems to only happen when I have the global cache variable in the code. I am running this code on Node v 10, not on a browser.
The error from the terminal
TypeError: WebAssembly Instantiation: Import #0 module="env" error: module is not an object or function
WebAssembly.instantiateStreaming(fetch("build/fib.wasm"),{env: {abort(msg,file,line,column){console.error("abort called at main.ts:"+line+":"+column);}},console: {logi(value){console.log('logi: '+value);}}}).then(result=>{const{ fib }=result.instance.exports;fib(123);});
an Object Literal whose keys are any number from 0 to ~200
Just noticed: From a performance perspective, an array with 200 elements will most likely yield better results:
varcache=newArray<i32>(200);
Now, when accessing a value, you can use value = unchecked(cache[num]), which also disables the usual range check where num is already know to be in range. Note that the array is initialized with all 0 values.
Well the 200 maximum limit was just for an example but that seems like an interesting approach to caching.
I seem to be facing a new problem however. When I try calculating the fibonacci of 50, it returns -298632863 which is because it already exceeds the i32 maximum limit since the fibonacci of 50 is 12,586,269,025 but when I try to use the i64 integers I get this type error
Uncaught (in promise) TypeError: wasm function signature contains illegal type
at WebAssembly.instantiateStreaming.then.result
The code hasn't changed much from my previous implementation
These solutions work fine. But the last two seem to need quite some wrapping code obviously.
Seems I might have to be using f64 for all my operations for good measure.
Is the interop a problem with AssemblyScript or browser engines for JavaScript? (If it's AssemblyScript related are there plans to fix it?)
Also, is there provided documentation on how to mitigate such problems? Because your wiki did not have these details.
There is a Binaryen pass that can transform i64 on the boundaries to a pair of i32s as well. To enable it, it should be sufficient to add --runPasses legalize-js-interface to the command line when invoking asc. I believe the respective function then returns the low 32 bits and there is an exported helper that can be called to retrieve the high bits.
Activity
[-]Adding memoization for Fibonacci[/-][+]Adding memoization for Fibonacci [Question][/+]dcodeIO commentedon Jul 6, 2018
Have you tried using a
Map<i32,i32>?hipstermojo commentedon Jul 6, 2018
So I tried using
Map<i32,i32>but then now the compiler brings up different errors concerning thegetmethod inMap. I am using TypeScript v 2.9.Here's the code I implemented. Maybe you could let me know where I went wrong
MaxGraey commentedon Jul 6, 2018
Everything works fine. Just see this example
By the way AssemblyScript doesn't depend on TypeScript package.
MaxGraey commentedon Jul 6, 2018
By the way for huge input numbers you can use analytical fib implementation:
hipstermojo commentedon Jul 6, 2018
Well now it compiles for sure however now the JavaScript code fails to "recognize" the exported code as either functions or objects. This seems to only happen when I have the global
cachevariable in the code. I am running this code on Node v 10, not on a browser.The error from the terminal
MaxGraey commentedon Jul 6, 2018
You JS side should looks like:
hipstermojo commentedon Jul 6, 2018
Everything works now. On the browser at least. Thanks.
dcodeIO commentedon Jul 7, 2018
Just noticed: From a performance perspective, an array with 200 elements will most likely yield better results:
Now, when accessing a value, you can use
value = unchecked(cache[num]), which also disables the usual range check wherenumis already know to be in range. Note that the array is initialized with all0values.hipstermojo commentedon Jul 9, 2018
Well the 200 maximum limit was just for an example but that seems like an interesting approach to caching.
I seem to be facing a new problem however. When I try calculating the fibonacci of 50, it returns
-298632863which is because it already exceeds thei32maximum limit since the fibonacci of 50 is12,586,269,025but when I try to use thei64integers I get this type errorThe code hasn't changed much from my previous implementation
MaxGraey commentedon Jul 9, 2018
It seems you try call
fibfrom JS, but JavaScript doesn't support interop withi64types yet. So you can do several variants:fib(num: f64): f64insteadfib(num: i64): i64. Valid integer range [0, 2^53-1]in JS:
PS 3. Another one (should be faster):
AS side:
JS Side:
hipstermojo commentedon Jul 10, 2018
These solutions work fine. But the last two seem to need quite some wrapping code obviously.
Seems I might have to be using
f64for all my operations for good measure.Is the interop a problem with AssemblyScript or browser engines for JavaScript? (If it's AssemblyScript related are there plans to fix it?)
Also, is there provided documentation on how to mitigate such problems? Because your wiki did not have these details.
MaxGraey commentedon Jul 10, 2018
This interop limitation comes from browsers and WebAssembly spec. Currently there is one big-int proposal which in Stage 3 and also this but not all browsers support BigInt yet.
dcodeIO commentedon Jul 10, 2018
There is a Binaryen pass that can transform i64 on the boundaries to a pair of i32s as well. To enable it, it should be sufficient to add
--runPasses legalize-js-interfaceto the command line when invokingasc. I believe the respective function then returns the low 32 bits and there is an exported helper that can be called to retrieve the high bits.