note description: "Summary description for {NUMBER_LOGIC}." author: "Colin LeMahieu" date: "$Date$" revision: "$Revision$" quote: "It is a free market that makes monopolies impossible. - Ayn Rand" deferred class SPECIAL_LOGIC inherit LIMB_MANIPULATION feature com_n (target: SPECIAL [NATURAL_32]; target_offset_a: INTEGER; op1: SPECIAL [NATURAL_32]; op1_offset_a: INTEGER; op1_count_a: INTEGER) require op1_count_a >= 1 local target_offset: INTEGER op1_offset: INTEGER op1_count: INTEGER do target_offset := target_offset_a op1_offset := op1_offset_a op1_count := op1_count_a from until op1_count = 0 loop target [target_offset] := op1 [op1_offset].bit_not target_offset := target_offset + 1 op1_offset := op1_offset + 1 op1_count := op1_count - 1 end end hamdist (op1: SPECIAL [NATURAL_32]; op1_offset_a: INTEGER; op2: SPECIAL [NATURAL_32]; op2_offset_a: INTEGER; n_a: INTEGER): INTEGER local p0: NATURAL_32 p1: NATURAL_32 p2: NATURAL_32 p3: NATURAL_32 x: NATURAL_32 p01: NATURAL_32 p23: NATURAL_32 i: INTEGER op1_offset: INTEGER n: INTEGER op2_offset: INTEGER do op2_offset := op2_offset_a n := n_a op1_offset := op1_offset_a from i := n |>> 2 until i = 0 loop p0 := op1 [op1_offset].bit_xor (op2 [op2_offset]) p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3) p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5) p1 := op1 [op1_offset + 1].bit_xor (op2 [op2_offset + 1]) p1 := p1 - (p1 |>> 1).bit_and (limb_max // 3) p1 := (p1 |>> 2).bit_and (limb_max // 5) + p1.bit_and (limb_max // 5) p01 := p0 + p1 p01 := (p01 |>> 4).bit_and (limb_max // 17) + p01.bit_and (limb_max // 17) p2 := op1 [op1_offset + 2].bit_xor (op2 [op2_offset + 2]) p2 := p2 - (p2 |>> 1).bit_and (limb_max // 3) p2 := (p2 |>> 2).bit_and (limb_max // 5) + p2.bit_and (limb_max // 5) p3 := op1 [op1_offset + 3].bit_xor (op2 [op2_offset + 3]) p3 := p3 - (p3 |>> 1).bit_and (limb_max // 3) p3 := (p3 |>> 2).bit_and (limb_max // 5) + p3.bit_and (limb_max // 5) p23 := p2 + p3 p23 := (p23 |>> 4).bit_and (limb_max // 17) + p23.bit_and (limb_max // 17) x := p01 + p23 x := (x |>> 8) + x x := (x |>> 16) + x Result := Result + x.bit_and (0xff).to_integer_32 op1_offset := op1_offset + 4 op2_offset := op2_offset + 4 i := i - 1 end n := n.bit_and (3) if n /= 0 then x := 0 from until n = 0 loop p0 := op1 [op1_offset].bit_xor (op2 [op2_offset]) p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3) p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5) p0 := ((p0 |>> 4) | p0).bit_and (limb_max // 17) x := x + p0 op1_offset := op1_offset + 1 op2_offset := op2_offset + 1 n := n - 1 end x := (x |>> 8) + x x := (x |>> 16) + x Result := Result + x.bit_and (0xff).to_integer_32 end end lshift (target: SPECIAL [NATURAL_32]; target_offset: INTEGER_32; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER_32; n: INTEGER_32; count: INTEGER_32; carry: CELL [NATURAL_32]) require target.valid_index (target_offset) target.valid_index (target_offset + n - 1) op1.valid_index (op1_offset) op1.valid_index (op1_offset + n - 1) count > 0 count < 32 local high_limb: NATURAL_32 low_limb: NATURAL_32 tnc: INTEGER_32 i: INTEGER_32 up: INTEGER_32 rp: INTEGER_32 do up := op1_offset + n rp := target_offset + n tnc := 32 - count up := up - 1 low_limb := op1 [up] carry.put (low_limb |>> tnc) high_limb := low_limb |<< count from i := n - 1 until i = 0 loop up := up - 1 low_limb := op1 [up] rp := rp - 1 target [rp] := high_limb.bit_or (low_limb |>> tnc) high_limb := low_limb |<< count i := i - 1 end rp := rp - 1 target [rp] := high_limb end rshift (target: SPECIAL [NATURAL_32]; target_offset: INTEGER_32; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER_32; n: INTEGER_32; count: INTEGER_32; carry: CELL [NATURAL_32]) local high_limb: NATURAL_32 low_limb: NATURAL_32 tnc: INTEGER_32 i: INTEGER_32 op1_cursor: INTEGER_32 target_cursor: INTEGER_32 do tnc := 32 - count op1_cursor := op1_offset high_limb := op1 [op1_cursor] op1_cursor := op1_cursor + 1 carry.put (high_limb |<< tnc) low_limb := high_limb |>> count from i := n - 1 until i = 0 loop high_limb := op1 [op1_cursor] op1_cursor := op1_cursor + 1 target [target_cursor] := low_limb.bit_or (high_limb |<< tnc) target_cursor := target_cursor + 1 low_limb := high_limb |>> count i := i - 1 end target [target_cursor] := low_limb end popcount (op1: SPECIAL [NATURAL_32]; op1_offset_a: INTEGER; n_a: INTEGER): INTEGER local p0: NATURAL_32 p1: NATURAL_32 p2: NATURAL_32 p3: NATURAL_32 x: NATURAL_32 p01: NATURAL_32 p23: NATURAL_32 i: INTEGER op1_offset: INTEGER n: INTEGER do n := n_a op1_offset := op1_offset_a from i := n |>> 2 until i = 0 loop p0 := op1 [op1_offset] p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3) p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5) p1 := op1 [op1_offset + 1] p1 := p1 - (p1 |>> 1).bit_and (limb_max // 3) p1 := (p1 |>> 2).bit_and (limb_max // 5) + p1.bit_and (limb_max // 5) p01 := p0 + p1 p01 := (p01 |>> 4).bit_and (limb_max // 17) + p01.bit_and (limb_max // 17) p2 := op1 [op1_offset + 2] p2 := p2 - (p2 |>> 1).bit_and (limb_max // 3) p2 := (p2 |>> 2).bit_and (limb_max // 5) + p2.bit_and (limb_max // 5) p3 := op1 [op1_offset + 3] p3 := p3 - (p3 |>> 1).bit_and (limb_max // 3) p3 := (p3 |>> 2).bit_and (limb_max // 5) + p3.bit_and (limb_max // 5) p23 := p2 + p3 p23 := (p23 |>> 4).bit_and (limb_max // 17) + p23.bit_and (limb_max // 17) x := p01 + p23 x := (x |>> 8) + x x := (x |>> 16) + x Result := Result + x.bit_and (0xff).to_integer_32 op1_offset := op1_offset + 4 i := i - 1 end n := n.bit_and (3) if n /= 0 then x := 0 from until n = 0 loop p0 := op1 [op1_offset] p0 := p0 - (p0 |>> 1).bit_and (limb_max // 3) p0 := (p0 |>> 2).bit_and (limb_max // 5) + p0.bit_and (limb_max // 5) p0 := ((p0 |>> 4) | p0).bit_and (limb_max // 17) x := x + p0 op1_offset := op1_offset + 1 n := n - 1 end x := (x |>> 8) + x x := (x |>> 16) + x Result := Result + x.bit_and (0xff).to_integer_32 end end bit_xor_lshift (target: SPECIAL [NATURAL_32] target_offset: INTEGER op1: SPECIAL [NATURAL_32] op1_offset: INTEGER op1_count: INTEGER op2: SPECIAL [NATURAL_32] op2_offset: INTEGER op2_count: INTEGER op2_lshift: INTEGER) require op2_lshift >= 0 op1 /= op2 target /= op2 op1_count = 0 or op1.valid_index (op1_offset) op1_count = 0 or op1.valid_index (op1_offset + op1_count - 1) op2_count = 0 or op2.valid_index (op2_offset) op2_count = 0 or op2.valid_index (op2_offset + op2_count - 1) (op1_count = 0 and op2_count = 0) or target.valid_index (target_offset) (op1_count = 0 and op2_count = 0) or target.valid_index (target_offset + op1_count.max (op2_count + bits_to_limbs (op2_lshift)) - 1) local op2_limb_high: NATURAL_32 op2_limb_low: NATURAL_32 op2_limb: NATURAL_32 cursor: INTEGER shift_limbs: INTEGER shift_bits: INTEGER do shift_limbs := op2_lshift // limb_bits shift_bits := op2_lshift \\ limb_bits target.copy_data (op1, op1_offset, target_offset, shift_limbs) from until cursor >= op2_count or cursor >= op1_count - shift_limbs loop op2_limb_low := op2_limb_high op2_limb_high := op2 [op2_offset + cursor] op2_limb := extract_limb (shift_bits, op2_limb_high, op2_limb_low) target [target_offset + shift_limbs + cursor] := op2_limb.bit_xor (op1 [op1_offset + shift_limbs + cursor]) cursor := cursor + 1 end if cursor >= op2_count then op2_limb_low := op2_limb_high op2_limb := extract_limb (shift_bits, 0, op2_limb_low) if cursor >= op1_count - shift_limbs then target [target_offset + shift_limbs + cursor] := op2_limb else target [target_offset + shift_limbs + cursor] := op2_limb.bit_xor (op1 [op1_offset + shift_limbs + cursor]) cursor := cursor + 1 target.copy_data (op1, op1_offset + shift_limbs + cursor, target_offset + shift_limbs + cursor, op1_count - cursor - shift_limbs) end else from until cursor >= op2_count loop op2_limb_low := op2_limb_high op2_limb_high := op2 [op2_offset + cursor] op2_limb := extract_limb (shift_bits, op2_limb_high, op2_limb_low) target [target_offset + shift_limbs + cursor] := op2_limb cursor := cursor + 1 end op2_limb_low := op2_limb_high op2_limb := extract_limb (shift_bits, 0, op2_limb_low) target [target_offset + shift_limbs + cursor] := op2_limb end end bit_xor (target: SPECIAL [NATURAL_32]; target_offset: INTEGER; op1: SPECIAL [NATURAL_32]; op1_offset: INTEGER; op1_count: INTEGER; op2: SPECIAL [NATURAL_32]; op2_offset: INTEGER; op2_count: INTEGER) require (op1_count = 0 and op2_count = 0) or target.valid_index (target_offset) (op1_count = 0 and op2_count = 0) or target.valid_index (target_offset + op1_count.max (op2_count) - 1) local cursor: INTEGER min: INTEGER do from min := op1_count.min (op2_count) until cursor >= min loop target [target_offset + cursor] := op1 [op1_offset + cursor].bit_xor (op2 [op2_offset + cursor]) cursor := cursor + 1 end if op1_count > op2_count then target.copy_data (op1, op1_offset + cursor, target_offset + cursor, op1_count - cursor) elseif op2_count > op1_count then target.copy_data (op2, op2_offset + cursor, target_offset + cursor, op2_count - cursor) end end end