//+------------------------------------------------------------------+ //| Test.mq5 | //| Copyright 2026, Niquel Mendoza. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Niquel Mendoza." #property link "https://www.mql5.com" #property version "1.00" #property strict //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include //+------------------------------------------------------------------+ //| Original bitwise/CLZ | //+------------------------------------------------------------------+ char Utf32_8Len(uint x) { const bool y = (x >> 15) != 1; x |= (1u << 5); x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; const static char rest_t[8] = {0, 0, 0, 0, 1, 2, 3, 4}; const char r = (32 - TSN::g_tsntables_clz32[((x * TSN_TABLES_CLZ_CONSTANT_MAGIC32) >> 27)]) >> 2; return r - rest_t[r - y]; } //+------------------------------------------------------------------+ //| Original: suma de comparaciones (sin short-circuit) | //+------------------------------------------------------------------+ char Utf32_8Len2(uint v) { return 1 + (v > 0x7F) + (v > 0x7FF) + (v > 0xFFFF); } //+------------------------------------------------------------------+ //| Original: if/else con short-circuit | //+------------------------------------------------------------------+ char Utf32_8Len3(uint v) { if(v < 0x80) return 1; else if(v < 0x800) return 2; else if(v < 0x10000) return 3; return 4; } //+------------------------------------------------------------------+ //| V4: if/else pero reordenado - chequea primero el caso MAS | //| probable con distribucion uniforme de 32 bits (v >= 0x10000) | //+------------------------------------------------------------------+ char Utf32_8Len4(uint v) { if(v >= 0x10000) return 4; else if(v >= 0x800) return 3; else if(v >= 0x80) return 2; return 1; } //+------------------------------------------------------------------+ //| V5: branchless con shifts/clz simple, sin tabla ni magic number | //| cuenta "cuantos umbrales supera" usando aritmetica de bits pura | //+------------------------------------------------------------------+ char Utf32_8Len5(uint v) { // en vez de 3 comparaciones con bool->int, usamos mascaras directas // -(x) en complemento a 2 da todo 1s si x!=0, todo 0s si x==0 // pero mas simple: aprovechamos que v>>7, v>>11, v>>16 colapsan a 0 // cuando v es menor al umbral correspondiente uint m1 = (uint)-(int)((v >> 7) != 0); // todo 1s o todo 0s uint m2 = (uint)-(int)((v >> 11) != 0); uint m3 = (uint)-(int)((v >> 16) != 0); return (char)(1 + (m1 & 1) + (m2 & 1) + (m3 & 1)); } //+------------------------------------------------------------------+ //| V6: ternarios anidados (el compilador podria tratarlos distinto | //| a if/else aunque sean logicamente equivalentes) | //+------------------------------------------------------------------+ char Utf32_8Len6(uint v) { return v < 0x80 ? 1 : (v < 0x800 ? 2 : (v < 0x10000 ? 3 : 4)); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { //--- int v; ulong a, b; const int N = 0xffffff; #define RUN_TEST(fn) \ MathSrand(1651); \ v = 0; \ a = GetMicrosecondCount(); \ for(int i = 0; i < N; i++) \ { \ v += fn(uint(MathRand()) & 0xff); \ } \ b = GetMicrosecondCount(); \ Print("time: ", (b - a), " v: ", v, " [" + #fn + "]"); RUN_TEST(Utf32_8Len) RUN_TEST(Utf32_8Len2) RUN_TEST(Utf32_8Len3) RUN_TEST(Utf32_8Len4) RUN_TEST(Utf32_8Len5) RUN_TEST(Utf32_8Len6) #undef RUN_TEST } //+------------------------------------------------------------------+