diff --git a/src/generator/writers/__snapshots__/writeSerialization.spec.ts.snap b/src/generator/writers/__snapshots__/writeSerialization.spec.ts.snap index 30db3674f..738551146 100644 --- a/src/generator/writers/__snapshots__/writeSerialization.spec.ts.snap +++ b/src/generator/writers/__snapshots__/writeSerialization.spec.ts.snap @@ -1741,6 +1741,44 @@ return result;", "name": "__tact_pow", "signature": "int __tact_pow(int base, int exp)", }, + { + "code": { + "code": "UBITSIZE", + "kind": "asm", + "shuffle": "", + }, + "comment": null, + "context": "stdlib", + "depends": Set {}, + "flags": Set {}, + "name": "__tact_log2_floor_unsafe", + "signature": "int __tact_log2_floor_unsafe(int num)", + }, + { + "code": { + "code": "if (num == 0) { return 0; } +int s = __tact_log2_floor_unsafe(num); +int x = (s == 1 ? (num - 1) / 2 + 1 : 1 << ((s + 1) / 2)); + +do { + int q = (muldivc(num, 1, x) - x) / 2; + x += q; +} until (q == 0); + +return x;", + "kind": "generic", + }, + "comment": null, + "context": "stdlib", + "depends": Set { + "__tact_log2_floor_unsafe", + }, + "flags": Set { + "inline", + }, + "name": "__tact_sqrt", + "signature": "int __tact_sqrt(int num)", + }, { "code": { "code": "var (r, ok) = __tact_dict_get(d, kl, k); @@ -6167,6 +6205,44 @@ return result;", "name": "__tact_pow", "signature": "int __tact_pow(int base, int exp)", }, + { + "code": { + "code": "UBITSIZE", + "kind": "asm", + "shuffle": "", + }, + "comment": null, + "context": "stdlib", + "depends": Set {}, + "flags": Set {}, + "name": "__tact_log2_floor_unsafe", + "signature": "int __tact_log2_floor_unsafe(int num)", + }, + { + "code": { + "code": "if (num == 0) { return 0; } +int s = __tact_log2_floor_unsafe(num); +int x = (s == 1 ? (num - 1) / 2 + 1 : 1 << ((s + 1) / 2)); + +do { + int q = (muldivc(num, 1, x) - x) / 2; + x += q; +} until (q == 0); + +return x;", + "kind": "generic", + }, + "comment": null, + "context": "stdlib", + "depends": Set { + "__tact_log2_floor_unsafe", + }, + "flags": Set { + "inline", + }, + "name": "__tact_sqrt", + "signature": "int __tact_sqrt(int num)", + }, { "code": { "code": "var (r, ok) = __tact_dict_get(d, kl, k); @@ -10593,6 +10669,44 @@ return result;", "name": "__tact_pow", "signature": "int __tact_pow(int base, int exp)", }, + { + "code": { + "code": "UBITSIZE", + "kind": "asm", + "shuffle": "", + }, + "comment": null, + "context": "stdlib", + "depends": Set {}, + "flags": Set {}, + "name": "__tact_log2_floor_unsafe", + "signature": "int __tact_log2_floor_unsafe(int num)", + }, + { + "code": { + "code": "if (num == 0) { return 0; } +int s = __tact_log2_floor_unsafe(num); +int x = (s == 1 ? (num - 1) / 2 + 1 : 1 << ((s + 1) / 2)); + +do { + int q = (muldivc(num, 1, x) - x) / 2; + x += q; +} until (q == 0); + +return x;", + "kind": "generic", + }, + "comment": null, + "context": "stdlib", + "depends": Set { + "__tact_log2_floor_unsafe", + }, + "flags": Set { + "inline", + }, + "name": "__tact_sqrt", + "signature": "int __tact_sqrt(int num)", + }, { "code": { "code": "var (r, ok) = __tact_dict_get(d, kl, k); diff --git a/src/generator/writers/writeStdlib.ts b/src/generator/writers/writeStdlib.ts index 4bd365603..8017451cd 100644 --- a/src/generator/writers/writeStdlib.ts +++ b/src/generator/writers/writeStdlib.ts @@ -1133,6 +1133,32 @@ export function writeStdlib(ctx: WriterContext): void { }); }); + ctx.fun(`__tact_log2_floor_unsafe`, () => { + ctx.signature(`int __tact_log2_floor_unsafe(int num)`); + ctx.context("stdlib"); + ctx.asm("", "UBITSIZE"); + }); + + ctx.fun(`__tact_sqrt`, () => { + ctx.signature(`int __tact_sqrt(int num)`); + ctx.flag("inline"); + ctx.context("stdlib"); + ctx.body(() => { + ctx.write(` + if (num == 0) { return 0; } + int s = ${ctx.used("__tact_log2_floor_unsafe")}(num); + int x = (s == 1 ? (num - 1) / 2 + 1 : 1 << ((s + 1) / 2)); + + do { + int q = (muldivc(num, 1, x) - x) / 2; + x += q; + } until (q == 0); + + return x; + `); + }); + }); + // generate dict operations for all combinations of key/value types for (const key of keyTypes) { for (const val of valTypes) { diff --git a/src/imports/stdlib.ts b/src/imports/stdlib.ts index 2d888b9e1..6266faca3 100644 --- a/src/imports/stdlib.ts +++ b/src/imports/stdlib.ts @@ -289,7 +289,8 @@ files['std/math.tact'] = 'bmFtZShfX3RhY3RfcG93KQpuYXRpdmUgcG93KGJhc2U6IEludCwgZXhwOiBJbnQpOiBJbnQ7Cgphc20gZnVuIHBvdzIoZXhwOiBJbnQpOiBJbnQgeyBQT1cyIH0KCmFz' + 'bSBmdW4gc2lnbih4OiBJbnQpOiBJbnQgeyBTR04gfQoKLy8gZmxvb3IoeCp5LzJeeikKYXNtIGZ1biBtdWxyc2hpZnQoeDogSW50LCB5OiBJbnQsIHo6IEludCk6IElu' + 'dCB7IE1VTFJTSElGVCB9CgovLyByb3VuZCh4KnkvMl56KQphc20gZnVuIG11bHJzaGlmdF9yb3VuZCh4OiBJbnQsIHk6IEludCwgejogSW50KTogSW50IHsgTVVMUlNI' + - 'SUZUUiB9CgovLyBjZWlsKHgqeS8yXnopCmFzbSBmdW4gbXVscnNoaWZ0X2NlaWwoeDogSW50LCB5OiBJbnQsIHo6IEludCk6IEludCB7IE1VTFJTSElGVEMgfQo='; + 'SUZUUiB9CgovLyBjZWlsKHgqeS8yXnopCmFzbSBmdW4gbXVscnNoaWZ0X2NlaWwoeDogSW50LCB5OiBJbnQsIHo6IEludCk6IEludCB7IE1VTFJTSElGVEMgfQoKQG5h' + + 'bWUoX190YWN0X3NxcnQpCm5hdGl2ZSBzcXJ0KG51bTogSW50KTogSW50Owo='; files['std/primitives.tact'] = 'cHJpbWl0aXZlIEludDsKcHJpbWl0aXZlIEJvb2w7CnByaW1pdGl2ZSBCdWlsZGVyOwpwcmltaXRpdmUgU2xpY2U7CnByaW1pdGl2ZSBDZWxsOwpwcmltaXRpdmUgQWRk' + 'cmVzczsKcHJpbWl0aXZlIFN0cmluZzsKcHJpbWl0aXZlIFN0cmluZ0J1aWxkZXI7'; diff --git a/stdlib/std/math.tact b/stdlib/std/math.tact index edb05bff3..987698b8d 100644 --- a/stdlib/std/math.tact +++ b/stdlib/std/math.tact @@ -71,3 +71,6 @@ asm fun mulrshift_round(x: Int, y: Int, z: Int): Int { MULRSHIFTR } // ceil(x*y/2^z) asm fun mulrshift_ceil(x: Int, y: Int, z: Int): Int { MULRSHIFTC } + +@name(__tact_sqrt) +native sqrt(num: Int): Int;