2016-01-22 2 views
1

Я пытаюсь преобразовать функцию javascript в скрипт C#. Одна из вещей, которую делает версия javascript, - это создать Uint32Array из существующего буфера. Float32ArrayC# эквивалент javascript TypedArray, созданный из буфера существующего массива?

Кто-нибудь знает, что эквивалент этого будет в C#? Я не говорю о том, что Float32Array и Uint32Array находятся в C#. Я говорю о том, как массив, набранный javascript, инициализируется с использованием буфера из переменной dst (см. Код) ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray Это важно, потому что другие массивы инициализируются позже после эта функция используется (например) var dstUint32 = new Uint32Array (dst.buffer) ...

Это код (src - это существующий Float32Array - см. бит начальных значений для этого ниже) ...

compileClassifier = function(src, width, scale, dst) { 
     width += 1; 
     if (!dst) dst = new Float32Array(src.length); 
     var dstUint32 = new Uint32Array(dst.buffer); 

     dstUint32[0] = src[0]; 
     dstUint32[1] = src[1]; 
     var dstIndex = 1; 
     for (var srcIndex = 1, iEnd = src.length - 1; srcIndex < iEnd;) { 
      dst[++dstIndex] = src[++srcIndex]; 

      var numComplexClassifiers = dstUint32[++dstIndex] = src[++srcIndex]; 
      for (var j = 0, jEnd = numComplexClassifiers; j < jEnd; ++j) { 

       var tilted = dst[++dstIndex] = src[++srcIndex]; 
       var numFeaturesTimes3 = dstUint32[++dstIndex] = src[++srcIndex] * 3; 
       if (tilted) { 
        for (var kEnd = dstIndex + numFeaturesTimes3; dstIndex < kEnd;) { 
         dstUint32[++dstIndex] = src[++srcIndex] + src[++srcIndex] * width; 
         dstUint32[++dstIndex] = src[++srcIndex] * (width + 1) + ((src[++srcIndex] * (width - 1)) << 16); 
         dst[++dstIndex] = src[++srcIndex]; 
        } 
       } else { 
        for (var kEnd = dstIndex + numFeaturesTimes3; dstIndex < kEnd;) { 
         dstUint32[++dstIndex] = src[++srcIndex] + src[++srcIndex] * width; 
         dstUint32[++dstIndex] = src[++srcIndex] + ((src[++srcIndex] * width) << 16); 
         dst[++dstIndex] = src[++srcIndex]; 
        } 
       } 

       var inverseClassifierThreshold = 1/src[++srcIndex]; 
       for (var k = 0; k < numFeaturesTimes3;) { 
        dst[dstIndex - k] *= inverseClassifierThreshold; 
        k += 3; 
       } 

       if (inverseClassifierThreshold < 0) { 
        dst[dstIndex + 2] = src[++srcIndex]; 
        dst[dstIndex + 1] = src[++srcIndex]; 
        dstIndex += 2; 
       } else { 
        dst[++dstIndex] = src[++srcIndex]; 
        dst[++dstIndex] = src[++srcIndex]; 
       } 
      } 
     } 
     dst = dst.subarray(0, dstIndex + 1); 
     return dst; 
    } 

переменная ЦСИ там создается из этого (это очень урезанная версия полная версия тысячи номеров длинных): -

var classifier = [20,20,0.8226894140243530,3,0,2,3,7,14,4,-1.,3,9,14,2,2.,4.0141958743333817e-003,0.0337941907346249,0.8378106951713562,0,2,1,2,18,4,-1.,7,2,6,4,3.,0.0151513395830989,0.1514132022857666,0.7488812208175659,0,2,1,7,15,9,-1.,1,10,15,3,3.,4.2109931819140911e-003,0.0900492817163467,0.6374819874763489,6.9566087722778320,16,0,2,5,6,2,6,-1.,5,9,2,3,2.,1.6227109590545297e-003,0.0693085864186287]; 
src = new Float32Array(classifier); 

Это то, что регистрируется в консоли для dstUint32 и dst соответственно с теми числами, которые установлены как src (функция не работает с этими числами, поскольку, как я говорю, фактический массив намного длиннее). Его интересный что почти ни один из номеров не соответствует исходный массив ...

[20, 20, 1062378438, 3, 0, 6, 1641, 61341710, 3279494571, 2109, 30670862, 1140399531, 1024093127, 1062632131, 0, 6, 469, 61341714, 3263430756, 475, 61341702, 1128661142, 1041959952, 1061140142, 0, 6, 1639, 138018831, 3278731586, 2341, 46006287, 1144134386, 1035496386, 1059271173, 1088330890, 16, 0, 6, 1409, 92012546, 3290042412, 2111, 46006274, 1150947372, 1032712617, 4294967295, 4294967295, 0, 4294967295, 4294967295, 4294967295, 0, 4294967295, 4294967295, 4294967295, 0, 4294967295, 4294967295, 4294967295, 0, 4294967295, 4294967295, 4294967295, 0, 4294967295] 


[2.802596928649634e-44, 2.802596928649634e-44, 0.822689414024353, 4.203895392974451e-45, 0, 8.407790785948902e-45, 2.2995307799570248e-42, 9.874165102541455e-37, -249.1158905029297, 2.955338461261039e-42, 7.787657921469055e-38, 498.2317810058594, 0.03379419073462486, 0.8378106951713562, 0, 8.407790785948902e-45, 6.572089797683392e-43, 9.874168689865524e-37, -66.00076293945312, 6.656167705542881e-43, 9.874157927893318e-37, 198.00228881835938, 0.1514132022857666, 0.7488812208175659, 0, 8.407790785948902e-45, 2.2967281830283752e-42, 5.597240788537616e-34, -237.47366333007812, 3.280439704984397e-42, 2.7918024463192472e-37, 712.4210205078125, 0.09004928171634674, 0.6374819874763489, 6.956608772277832, 2.2420775429197073e-44, 0, 8.407790785948902e-45, 1.9744295362336673e-42, 1.1848984491218286e-35, -616.252685546875, 2.958141058189689e-42, 2.7917995316184414e-37, 1232.50537109375, 0.06930858641862869, NaN, NaN, 0, NaN, NaN, NaN, 0, NaN, NaN, NaN, 0, NaN, NaN, NaN, 0, NaN, NaN, NaN, 0, NaN] 

Таким образом, вы можете увидеть здесь, что код

dstUint32[0] = src[0]; 
dstUint32[1] = src[1]; 

кажется установили ОБА dstUint32 [0]/dstUint32 [1] И dst [0]/dst [1] на что-то, только в dst [0]/dst [1] значение регистрируется как 2.802596928649634e-44, а не 20?

+4

«Float32Array» в C# является 'float []' –

+1

И 'UInt32Array' в C# будет' uint [] '. –

+0

Остальная часть кода должна быть в основном одинаковой. За исключением того, что вам нужно будет использовать 'float' для' uint'. –

ответ

5
  • Эквивалент js UInt32Array является UInt32[].
  • Эквивалент js Float32Array: float[].
  • Эквивалент ArrayBuffer: byte[].

Набранные массивы с набором символов: просмотров на буфер массива. Таким образом, элемент в UInt32Array не является отличным плавающим, а содержимое физического хранилища - бит - переинтерпретировано как плавающее.

Чтобы сделать это на C#, вам нужно сделать одну из двух вещей.

Если вы заботитесь о разделении на ArrayBuffer

Если вы заботитесь о разделении на ArrayBuffer, то есть вам нужно изменение в одном массиве, чтобы показать в другом массиве сразу, то вам нужно реализовать все это. C# не предлагает это из коробки. Чтобы достичь этого, вам нужно будет воспользоваться объектами InteropServices.Marshal. Они позволят вам получить доступ к основной памяти.

Если вы не заботитесь о разделении на ArrayBuffer

Если вы просто хотите конвертировать в одном направлении, а затем, возможно, позже преобразовать обратно, но вы не нужны изменения, чтобы быть видимыми немедленно, или для использования совместно используемого ArrayBuffer вам проще работать.

  • Создать MemoryStream,
  • записывать элементы float32 из массива
  • читать элементы UInt32

Что-то вроде этого:

static byte[] ReinterpretAsByteArray(UInt32[] a) 
    { 
     using (MemoryStream s = new MemoryStream()) 
     { 
      using (BinaryWriter w = new BinaryWriter(s, Encoding.Unicode, true)) 
      { 
       for (int i = 0; i < a.Length; i++) 
       { 
        w.Write(a[i]); 
       } 
      } 
      return s.ToArray(); 
     } 
    } 
    static float[] ReinterpretAsFloatArray(byte[] b) { 
     using (MemoryStream s = new MemoryStream(b, false)) { 
      using (BinaryReader r = new BinaryReader(s, Encoding.Unicode, true)) 
      { 
       float[] f = new float[b.Length/4]; // 4 = sizeof float 
       for (int i = 0; i < b.Length; i++) 
       { 
        f[i] = r.ReadSingle(); 
       } 
       return f; 
      } 
     } 
    }  

Вам нужно будет написать аналогичную функцию для преобразования байтового массива в массив Uint32 и преобразования массива float в массив байтов, но это ma изменение двух линий.

+0

Правильно укажите свои переменные. Легко потерять следы s, b, f, i и т. Д. –

+0

@Ben благодарит так много за эту замечательную информацию ... рассматривает «эквивалент js Float32Array is float []» - im not sure, если это разные в Unity, но в Unity, когда я Debug.Log значения в примере, который я дал при преобразовании в float, они намного короче, то есть 0.822689414024353 заканчивается как 0,8226894, но исходные значения, когда я использую массив «Неявно типизированный» для создания массив выходит так же, и сам массив получает значение как двойной массив, а не массив с плавающей точкой. Итак, эквивалент C# для Float32Array фактически представляет собой двойной массив или что-то еще что-то путает? –

+0

Все номера в JavaScript являются двойными (Float64), не существует целочисленных типов (теоретически). Целое число javascript - это float, показатель которого равен нулю. Когда вы храните их в Float32Array, они преобразуются в Float32 (с потерей точности). Когда вы храните их в Int32Array, они преобразуются в Int32 (без потери точности, если число находится в диапазоне Int32). Когда вы извлекаете их из массива, они преобразуются обратно в Float64. (Предостережение: двигатель может оптимизировать их и использовать целые числа внутри для некоторых целей, но эффект *, как если бы все они были удвоены) – Ben

Смежные вопросы