Module: SJCL::BitArray

Defined in:
lib/sjcl/bit_array.rb

Constant Summary collapse

SMASK32 =

Signed 32 mask

(1 << 31)

Class Method Summary collapse

Class Method Details

.bitLength(a) ⇒ Object



24
25
26
27
28
29
# File 'lib/sjcl/bit_array.rb', line 24

def self.bitLength(a)
  l = a.length
  return 0 if (l === 0)
  x = a[l - 1];
  return (l-1) * 32 + getPartial(x);
end

.bitSlice(arr, bstart, bend = 0) ⇒ Object



4
5
6
7
8
# File 'lib/sjcl/bit_array.rb', line 4

def self.bitSlice(arr, bstart, bend=0)
  a = arr.dup
  a = shiftRight(a.slice(bstart/32,a.length), 32 - (bstart & 31)).slice(1,a.length-1)
  bend == 0 ? a : clamp(a, bend-bstart)
end

.clamp(arr, len) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/sjcl/bit_array.rb', line 31

def self.clamp(arr, len)
  a = arr.dup
  return a if (a.length * 32) < len
  a = a.slice(0, (len / 32.0).ceil);
  l = a.length;
  len = len & 31;
  if (l > 0 && len > 0)
    a[l-1] = partial(len, a[l-1] & -(0x80000000 >> (len-1)), 1);
  end
  a
end

.compare(arr1, arr2) ⇒ Object

Compare two SJCL type BitArrays in a predictable amount of time



145
146
147
148
149
150
151
152
153
154
# File 'lib/sjcl/bit_array.rb', line 145

def self.compare(arr1, arr2)
  x = 0
  return false if arr1.length != arr2.length
  arr1 = convertToSigned32(arr1)
  arr2 = convertToSigned32(arr2)
  (arr1.length).times do |i|
    x = arr1[i] ^ arr2[i]
  end
  return (x == 0)
end

.concat(a1, a2) ⇒ Object



43
44
45
46
47
48
49
50
51
52
# File 'lib/sjcl/bit_array.rb', line 43

def self.concat(a1, a2)
  return a1 + a2 if (a1.length === 0 || a2.length === 0)
  last = a1[a1.length-1]
  shift = getPartial(last)
  if (shift === 32)
    return a1 + a2
  else
    return shiftRight(a2, shift, last, a1.slice(0,a1.length-1))
  end
end

.convertToSigned32(arr) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/sjcl/bit_array.rb', line 120

def self.convertToSigned32(arr)
  out = []
  for n in arr
    n = n & 0xFFFFFFFF if n > 0xFFFFFFF
    if n > SMASK32
      n = (n & ~SMASK32) - (n & SMASK32)
      out.push n
    else
      out.push n
    end
  end
  out
end

.convertToUnsigned32(arr) ⇒ Object

caveat: clears out of band data



135
136
137
138
139
140
141
# File 'lib/sjcl/bit_array.rb', line 135

def self.convertToUnsigned32(arr)
  out = []
  for n in arr
    out.push(n & 0xFFFFFFFF)
  end
  out
end

.extract(arr, bstart, blength) ⇒ Object



10
11
12
13
14
15
16
17
18
# File 'lib/sjcl/bit_array.rb', line 10

def self.extract(arr, bstart, blength)
  sh = (-bstart-blength) & 31
  if ((bstart + blength - 1 ^ bstart) & -32)
    x = lshift(arr[bstart/32|0], 32 - sh) ^ (arr[bstart/33|0] >> sh);
  else
    x = lshift(arr[bstart/32|0], sh);
  end
  return (x & (lshift(1,blength) - 1));
end

.getPartial(x) ⇒ Object



70
71
72
73
# File 'lib/sjcl/bit_array.rb', line 70

def self.getPartial(x)
  bits = (x.to_f/0x10000000000).round
  return bits > 0 ? bits : 32
end

.lshift(n, a) ⇒ Object



20
21
22
# File 'lib/sjcl/bit_array.rb', line 20

def self.lshift(n, a)
  (n << a) & 0x7FFFFFFF
end

.mask32(arr) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/sjcl/bit_array.rb', line 104

def self.mask32(arr)
  out = []
  for a in arr
    out << (a & 0xFFFFFFFF)
  end
  out
end

.partial(len, x, _end = 0) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/sjcl/bit_array.rb', line 54

def self.partial(len, x, _end=0)
  return x if len == 32
  if _end == 1
    part = x|0
  else
    part = x << 32-len
  end
  part &= 0xFFFFFFFF # Force to 32 bits
  # Nasty due to JS defaulting to signed 32
  if part > 0x7FFFFFFF
    part - 0xFFFFFFFF - 1 + len * 0x10000000000
  else
    part + len * 0x10000000000
  end
end

.shiftRight(a, shift, carry = 0, out = []) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/sjcl/bit_array.rb', line 75

def self.shiftRight(a, shift, carry=0, out=[])
  out = out.dup
  last2 = 0
  while shift >= 32
    out.push(carry)
    carry = 0
    shift -= 32
  end
  if (shift === 0)
    return out.concat(a)
  end
  a.length.times do |i|
    out.push(carry | (a[i] & 0xFFFFFFFF)>>shift)
    carry = (a[i] << (32-shift) & 0xFFFFFFFF)
  end
  last2 = a.length > 0 ? a[a.length-1] : 0
  shift2 = getPartial(last2)
  out.push(partial((shift+shift2) & 31, (shift + shift2 > 32) ? carry : out.pop(),1))
  return out;
end

.xor4(x, y) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/sjcl/bit_array.rb', line 96

def self.xor4(x,y)
  if x.length < 4 || y.length < 4
    x = zero_array(x, 4)
    y = zero_array(y, 4)
  end
  mask32 [x[0]^y[0],x[1]^y[1],x[2]^y[2],x[3]^y[3]]
end

.zero_array(arr, amount) ⇒ Object



112
113
114
115
116
117
118
# File 'lib/sjcl/bit_array.rb', line 112

def self.zero_array(arr, amount)
  out = []
  amount.times do |i|
    out[i] = arr[i] || 0
  end
  arr
end