Просмотр исходного кода

upd factorial - u128, return binary

221V 1 неделя назад
Родитель
Сommit
b3d921e7f3
2 измененных файлов с 33 добавлено и 37 удалено
  1. 15 9
      README.md
  2. 18 28
      niftest.zig

+ 15 - 9
README.md

@@ -18,19 +18,25 @@ Eshell V13.2  (abort with ^G)
 2> niftest:hello().
 "Hello world!"
 3> niftest:factorial(5).
-"120"
-4> niftest:factorial(20).
-"2432902008176640000"
-5> niftest:factorial(34).
-"295232799039604140847618609643520000000"
-6> niftest:factorial(35).
+<<"x">>
+4> binary:decode_unsigned(niftest:factorial(5)).
+120
+5> niftest:factorial(20).
+<<33,195,103,124,130,180,0,0>>
+6> binary:decode_unsigned(niftest:factorial(20)).
+2432902008176640000
+7> niftest:factorial(34).
+<<222,27,196,209,158,252,172,130,68,93,167,91,0,0,0,0>>
+8> binary:decode_unsigned(niftest:factorial(34)).
+295232799039604140847618609643520000000
+9> niftest:factorial(35).
 {error,"input too large, max is 34"}
-7> niftest:factorial(-5).
+10> niftest:factorial(-5).
 ** exception error: bad argument
      in function  niftest:factorial/1
         called as niftest:factorial(-5)
-8> q().
-
+11> q().
+ok
 
 
 

+ 18 - 28
niftest.zig

@@ -13,31 +13,6 @@ pub export fn hello(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_N
 }
 
 
-fn u128_to_buf(value: u128, buffer: *align(1) [40]u8) usize{
-  if(value == 0){
-    buffer[0] = '0';
-    return 1;
-  }
-  
-  var i: usize = 0;
-  var n = value;
-  while(n > 0){
-    buffer[i] = @as(u8, @intCast('0' + (n % 10)) );
-    n /= 10;
-    i += 1;
-  }
-  
-  var j: usize = 0;
-  while(j < i / 2) : (j += 1){
-    const temp = buffer[j];
-    buffer[j] = buffer[i - 1 - j];
-    buffer[i - 1 - j] = temp;
-  }
-  
-  return i;
-}
-
-
 pub export fn factorial(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.ERL_NIF_TERM) erl.ERL_NIF_TERM{
   if(argc != 1){
     return erl.enif_make_badarg(env);
@@ -62,10 +37,25 @@ pub export fn factorial(env: ?*erl.ErlNifEnv, argc: c_int, argv: [*c]const erl.E
     result *= i;
   }
   
-  var buf: [40]u8 = undefined;
-  const len = u128_to_buf(result, &buf);
+  var num_bytes: usize = 1;
+  var temp = result;
+  while(temp > 255) : (temp >>= 8){
+    num_bytes += 1;
+  }
+  
+  var bin: erl.ErlNifBinary = undefined; // for return binary in big-endian
+  if(erl.enif_alloc_binary(num_bytes, &bin) == 0){
+    return erl.enif_make_badarg(env); // alloc faild
+  }
+  
+  temp = result;
+  var idx = num_bytes;
+  while(idx > 0) : (idx -= 1){
+    bin.data[idx - 1] = @as(u8, @intCast(temp & 0xFF) );
+    temp >>= 8;
+  }
   
-  return erl.enif_make_string_len(env, buf[0..len].ptr, len, 1); // , ERL_NIF_LATIN1);
+  return erl.enif_make_binary(env, &bin);
 }