note description: "Summary description for {INTEGER_X_LOGIC}." author: "Colin LeMahieu" date: "$Date$" revision: "$Revision$" quote: "The politicians don't just want your money. They want your soul. They want you to be worn down by taxes until you are dependent and helpless. - James Dale Davidson, National Taxpayers Union" deferred class INTEGER_X_LOGIC inherit INTEGER_X_FACILITIES SPECIAL_ARITHMETIC rename bit_xor_lshift as bit_xor_lshift_special, bit_xor as bit_xor_special end SPECIAL_UTILITY feature bit_and (target: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X) local op1_ptr: SPECIAL [NATURAL_32] op1_ptr_offset: INTEGER op2_ptr: SPECIAL [NATURAL_32] op2_ptr_offset: INTEGER op1_size: INTEGER op2_size: INTEGER res_ptr: SPECIAL [NATURAL_32] res_ptr_offset: INTEGER res_size: INTEGER i: INTEGER junk: NATURAL_32 done: BOOLEAN opx: SPECIAL [NATURAL_32] opx_offset: INTEGER cy: NATURAL_32 res_alloc: INTEGER tmp_special: SPECIAL [NATURAL_32] tmp_integer: INTEGER tmp_integer_x: READABLE_INTEGER_X op1: READABLE_INTEGER_X op2: READABLE_INTEGER_X carry: CELL [NATURAL_32] do create carry.put (0) op1 := op1_a op2 := op2_a op1_size := op1.count op2_size := op2.count op1_ptr := op1.item op2_ptr := op2.item res_ptr := target.item if op1_size >= 0 then if op2_size >= 0 then res_size := op1_size.min (op2_size) from i := res_size - 1 until i < 0 or else op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i]) /= 0 loop i := i - 1 end res_size := i + 1 target.resize (res_size) res_ptr := target.item op1_ptr := op1.item op2_ptr := op2.item target.count := res_size if res_size /= 0 then add_n (res_ptr, res_ptr_offset, op1_ptr, op1_ptr_offset, op2_ptr, op2_ptr_offset, res_size, carry) junk := carry.item end done := True end else if op2_size < 0 then op1_size := -op1_size op2_size := -op2_size res_alloc := 1 + op1_size.max (op2_size) create opx.make_filled (0, op1_size) sub_1 (opx, opx_offset, op1_ptr, op1_ptr_offset, op1_size, 1, carry) junk := carry.item op1_ptr := opx create opx.make_filled (0, op2_size) sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry) junk := carry.item op2_ptr := opx target.resize (res_alloc) res_ptr := target.item if op1_size >= op2_size then res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size) from i := op2_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i]) i := i - 1 end res_size := op1_size else res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size) from i := op1_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i]) i := i - 1 end res_size := op2_size end add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry) cy := carry.item if cy /= 0 then res_ptr [res_ptr_offset + res_size] := cy res_size := res_size + 1 end target.count := -res_size done := True else tmp_integer_x := op1 op1 := op2 op2 := tmp_integer_x tmp_special := op1_ptr op1_ptr := op2_ptr op2_ptr := tmp_special tmp_integer := op1_ptr_offset op1_ptr_offset := op2_ptr_offset op2_ptr_offset := tmp_integer end end if not done then op2_size := -op2_size create opx.make_filled (0, op2_size) sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry) junk := carry.item op2_ptr := opx if op1_size > op2_size then res_size := op1_size target.resize (res_size) res_ptr := target.item op1_ptr := op1.item res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, res_size - op2_size) from i := op2_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i].bit_not) i := i - 1 end target.count := res_size else from i := op1_size - 1 until i < 0 or else op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i].bit_not) /= 0 loop i := i - 1 end res_size := i + 1 target.resize (res_size) res_ptr := target.item op1_ptr := op1.item from i := res_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i].bit_not) i := i - 1 end target.count := res_size end end end bit_clear (op: READABLE_INTEGER_X; bit_index: INTEGER_32) -- Clear bit `bit_index' in `rop'. local dsize: INTEGER_32 dp: SPECIAL [NATURAL_32] dp_offset: INTEGER limb_index: INTEGER dlimb: NATURAL_32 zero_bound: INTEGER i: INTEGER_32 done: BOOLEAN do dsize := op.count dp := op.item limb_index := bit_index // limb_bits if dsize >= 0 then if limb_index < dsize then dlimb := dp [dp_offset + limb_index] dlimb := dlimb.bit_and ((1 |<< (bit_index \\ limb_bits)).bit_not.to_natural_32) dp [dp_offset + limb_index] := dlimb if dlimb = 0 and limb_index = dsize - 1 then from dsize := dsize - 1 until dsize <= 0 or dp [dp_offset + dsize - 1] /= 0 loop dsize := dsize - 1 end op.count := dsize end end else dsize := -dsize from zero_bound := 0 until dp [dp_offset + zero_bound] /= 0 loop zero_bound := zero_bound + 1 end if limb_index > zero_bound then if limb_index < dsize then dp [dp_offset + limb_index] := dp [dp_offset + limb_index].bit_or ((1 |<< (bit_index \\ limb_bits)).to_natural_32) else op.resize (limb_index + 1) dp := op.item dp.fill_with (0, dp_offset + dsize, dp_offset + dsize + (limb_index - dsize) - 1) dp [dp_offset + limb_index] := (1 |<< (bit_index \\ (limb_bits))).to_natural_32 op.count := - (limb_index + 1) end elseif limb_index = zero_bound then dp [dp_offset + limb_index] := (dp [dp_offset + limb_index] - 1).bit_or ((1 |<< (bit_index \\ limb_bits)).to_natural_32) if dp [dp_offset + limb_index] = 0 then from i := limb_index + 1 until i >= dsize or done loop dp [dp_offset + 1] := dp [dp_offset + 1] + 1 if dp [dp_offset + i] = 0 then done := True else i := i + 1 end end if not done then dsize := dsize + 1 op.resize (dsize) dp [dp_offset + i] := 1 op.count := -dsize end end end end end bit_one_complement (target: READABLE_INTEGER_X; op: READABLE_INTEGER_X) -- Set `rop' to the one's complement of `op'. local src: READABLE_INTEGER_X size: INTEGER_32 cy: NATURAL_32 junk2: NATURAL_32 carry: CELL [NATURAL_32] do create carry.put (0) src := op size := src.count if size >= 0 then target.resize (size + 1) if size = 0 then target.item [0] := 1 target.count := -1 else add_1 (target.item, 0, src.item, 0, size, 1, carry) cy := carry.item if cy /= 0 then target.item [size] := cy size := size + 1 end target.count := -size end else size := -size target.resize (size) sub_1 (target.item, 0, src.item, 0, size, 1, carry) junk2 := carry.item if target.item [size - 1] = 0 then size := size - 1 end target.count := size end end bit_complement (d: READABLE_INTEGER_X; bit_index: INTEGER_32) local dsize: INTEGER dp: SPECIAL [NATURAL_32] limb_index: INTEGER bit_l: NATURAL_32 x: NATURAL_32 i: INTEGER c: NATURAL_32 junk: NATURAL_32 carry: CELL [NATURAL_32] do create carry.put (0) dsize := d.count.abs dp := d.item limb_index := bit_index // limb_bits bit_l := (1).to_natural_32 |<< (bit_index \\ limb_bits) if limb_index >= dsize then d.resize (limb_index + 1) dp := d.item dsize := limb_index + 1 end if d.count >= 0 then dp [limb_index] := dp [limb_index].bit_xor (bit_l) dsize := normalize (dp, 0, dsize) d.count := dsize else x := 0 - dp [limb_index] from i := limb_index - 1 until i < 0 loop if dp [i] /= 0 then x := x - 1 i := 0 end i := i - 1 end if x.bit_and (bit_l) /= 0 then d.resize (dsize + 1) dp := d.item add_1 (dp, limb_index, dp, limb_index, dsize - limb_index, bit_l, carry) c := carry.item dp [dsize] := c dsize := dsize + c.to_integer_32 else sub_1 (dp, limb_index, dp, limb_index, dsize + limb_index, bit_l, carry) junk := carry.item dsize := normalize (dp, 0, dsize) d.count := -dsize end end end bit_or (res: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X; op2_a: READABLE_INTEGER_X) local op1_ptr: SPECIAL [NATURAL_32] op1_ptr_offset: INTEGER op2_ptr: SPECIAL [NATURAL_32] op2_ptr_offset: INTEGER op1_size: INTEGER op2_size: INTEGER res_ptr: SPECIAL [NATURAL_32] res_ptr_offset: INTEGER res_size: INTEGER i: INTEGER done: BOOLEAN opx: SPECIAL [NATURAL_32] opx_offset: INTEGER cy: NATURAL_32 junk: NATURAL_32 tmp_special: SPECIAL [NATURAL_32] tmp_integer: INTEGER tmp_integer_x: READABLE_INTEGER_X op1: READABLE_INTEGER_X op2: READABLE_INTEGER_X res_alloc: INTEGER count: INTEGER carry: CELL [NATURAL_32] do create carry.put (0) op1 := op1_a op2 := op2_a op1_size := op1.count op2_size := op2.count op1_ptr := op1.item op2_ptr := op2.item res_ptr := res.item if op1_size >= 0 then if op2_size >= 0 then if op1_size >= op2_size then res.resize (op1_size) op1_ptr := op1.item op2_ptr := op2.item res_ptr := res.item if res_ptr /= op1_ptr then res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size) end from i := op2_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i]) i := i - 1 end res_size := op1_size else res.resize (op2_size) op1_ptr := op1.item op2_ptr := op2.item res_ptr := res.item if res_ptr /= op2_ptr then res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size) end from i := op1_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_or (op2_ptr [op2_ptr_offset + i]) i := i - 1 end end res_size := op2_size done := True end else if op2_size < 0 then op1_size := -op1_size op2_size := -op2_size res_size := op1_size.min (op2_size) create opx.make_filled (0, res_size) sub_1 (opx, opx_offset, op1_ptr, op1_ptr_offset, res_size, 1, carry) junk := carry.item op1_ptr := opx create opx.make_filled (0, res_size) sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, res_size, 1, carry) junk := carry.item op2_ptr := opx res.resize (res_size) res_ptr := res.item from i := res_size - 1 until i < 0 or else op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i]) /= 0 loop i := i - 1 end res_size := i + 1 if res_size /= 0 then from i := res_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_and (op2_ptr [op2_ptr_offset + i]) i := i - 1 end add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry) cy := carry.item if cy /= 0 then res_ptr [res_ptr_offset + res_size] := cy res_size := res_size + 1 end else res_ptr [res_ptr_offset] := 1 res_size := 1 end res.count := -res_size done := True else tmp_integer_x := op1 op1 := op2 op2 := tmp_integer_x tmp_special := op1_ptr op1_ptr := op2_ptr op2_ptr := tmp_special tmp_integer := op1_ptr_offset op1_ptr_offset := op2_ptr_offset op2_ptr_offset := tmp_integer end end if not done then op2_size := -op2_size res_alloc := op2_size create opx.make_filled (0, op2_size) sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry) junk := carry.item op2_ptr := opx op2_size := op2_size - (op2_ptr [op2_ptr_offset + op2_size - 1] = 0).to_integer res.resize (res_alloc) op1_ptr := op1.item res_ptr := res.item if op1_size >= op2_size then from i := op2_size - 1 until i < 0 or else op1_ptr [op1_ptr_offset + i].bit_not.bit_and (op2_ptr [op2_ptr_offset + i]) /= 0 loop i := i - 1 end res_size := i + 1 count := res_size else res_size := op2_size res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size) count := op1_size end if res_size /= 0 then from i := count - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_not.bit_and (op2_ptr [op2_ptr_offset + i]) i := i - 1 end add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry) cy := carry.item if cy /= 0 then res_ptr [res_ptr_offset + res_size] := cy res_size := res_size + 1 else res_ptr [res_ptr_offset] := 1 res_size := 1 end res.count := -res_size end end end bit_scan_0 (op: READABLE_INTEGER_X; starting_bit: INTEGER_32): INTEGER -- Scan `op', starting from bit `starting_bit', towards more significant bits, until the first 0 -- bit is found. -- Return the index of the found bit. -- The least significant bit is number 0. -- If the bit at `starting_bit' is already what's sought, then `starting_bit' is returned. -- If there's no bit found, then ULONG_MAX is returned. -- This will happen past the end of a negative number. local u_ptr: INTEGER_32 size: INTEGER_32 abs_size: INTEGER_32 u_end: INTEGER_32 starting_limb: INTEGER_32 p: INTEGER_32 limb: NATURAL_32 cnt: INTEGER_32 done: BOOLEAN q: INTEGER_32 do size := op.count abs_size := size.abs u_end := abs_size starting_limb := starting_bit // (4 |<< 3) p := starting_limb if starting_limb >= abs_size then if size >= 0 then Result := starting_bit else Result := Result.max_value end else limb := op.item [p] if size >= 0 then limb := limb.bit_or ((1 |<< (starting_bit \\ (4 |<< 3))).to_natural_32) from until limb /= (0).to_natural_32.bit_not or done loop p := p + 1 if p = u_end then done := true Result := abs_size * 4 |<< 3 else limb := op.item [p] end end if not done then limb := limb.bit_not end else q := p from until q = u_ptr or done loop q := q - 1 if op.item [q] /= 0 then done := true end end if not done then limb := limb - 1 end limb := limb.bit_and (({NATURAL_32} 0).bit_not |<< (starting_bit \\ (4 |<< 3))) if limb = 0 then p := p + 1 if p = u_end then Result := Result.max_value else from limb := op.item [p] until limb /= 0 loop p := p + 1 end end end end cnt := trailing_zeros (op.item [limb.to_integer_32]) Result := p - u_ptr + cnt end end bit_scan_1 (op1: READABLE_INTEGER_X; starting_bit: INTEGER): INTEGER local u_ptr: SPECIAL [NATURAL_32] u_ptr_offset: INTEGER size: INTEGER abs_size: INTEGER u_end: INTEGER starting_limb: INTEGER p: INTEGER limb: NATURAL_32 count: INTEGER q: INTEGER inverted: NATURAL_32 got_limb: BOOLEAN do u_ptr := op1.item size := op1.count abs_size := size.abs u_end := u_ptr_offset + abs_size starting_limb := starting_bit // limb_bits p := u_ptr_offset + starting_limb if starting_limb >= abs_size then if size >= 0 then Result := Result.max_value else Result := starting_bit end end limb := u_ptr [p] if size >= 0 and limb.bit_and (limb.max_value |<< (starting_bit \\ limb_bits)) = 0 and p + 1 = u_end then Result := Result.max_value else if size >= 0 then limb := limb.bit_and (limb.max_value |<< (starting_bit \\ limb_bits)) if limb = 0 then p := p + 1 from limb := u_ptr [p] p := p + 1 until limb /= 0 loop limb := u_ptr [p] p := p + 1 end end else q := p from inverted := 0 until q = u_ptr_offset or inverted /= 0 loop q := q - 1 inverted := u_ptr [q] end if inverted = 0 then if limb = 0 then from limb := 1 until limb = 0 loop p := p + 1 limb := u_ptr [p] end limb := 0 - limb got_limb := True else limb := limb - 1 end end if not got_limb then limb := limb.bit_or ((1).to_natural_32 |<< (starting_bit \\ limb_bits) - 1) from limb := 0 p := p + 1 if p /= u_end then limb := u_ptr [p] end until p = u_end or limb = limb.max_value loop p := p + 1 if p /= u_end then limb := u_ptr [p] end end if p = u_end then Result := abs_size * limb_bits else limb := limb.bit_not count := trailing_zeros (limb) Result := (p - u_ptr_offset) * limb_bits + count end else count := trailing_zeros (limb) Result := (p - u_ptr_offset) * limb_bits + count end end end end bit_set (op: READABLE_INTEGER_X; bit_index: INTEGER_32) -- Set bit `bit_index' in `rop'. local dsize: INTEGER_32 dp: INTEGER_32 limb_index: INTEGER_32 dst: INTEGER_32 n: INTEGER_32 zero_bound: INTEGER_32 dlimb: NATURAL_32 i: INTEGER_32 done: BOOLEAN x: NATURAL_32 p: INTEGER_32 last_p: NATURAL_32 do dsize := op.count dp := 0 limb_index := bit_index // limb_bits if dsize >= 0 then if limb_index < dsize then op.item [dp + limb_index] := op.item [dp + limb_index].bit_or ((1).to_natural_32 |<< (bit_index \\ limb_bits)) op.count := dsize else op.resize (limb_index + 1) if limb_index - dsize /= 0 then dst := dp + dsize n := limb_index - dsize from op.item [dst] := 0 dst := dst + 1 n := n - 1 until n = 0 loop op.item [dst] := 0 dst := dst + 1 n := n - 1 end end op.item [dp + limb_index] := (1 |<< (bit_index \\ limb_bits)).to_natural_32 op.count := limb_index + 1 end else dsize := -dsize from zero_bound := 0 until op.item [dp + zero_bound] /= 0 loop zero_bound := zero_bound + 1 end if limb_index > zero_bound then if limb_index < dsize then dlimb := op.item [dp + limb_index] dlimb := dlimb.bit_and ((1 |<< (bit_index \\ limb_bits)).bit_not.to_natural_32) op.item [dp + limb_index] := dlimb if dlimb = 0 and limb_index = dsize - 1 then from dsize := dsize - 1 until dsize <= 0 or op.item [dp + dsize - 1] /= 0 loop dsize := dsize - 1 end op.count := -dsize end end elseif limb_index = zero_bound then op.item [dp + limb_index] := (op.item [dp + limb_index] - 1).bit_and (((1).to_natural_32 |<< (bit_index \\ limb_bits)).bit_not) - 1 if op.item [dp + limb_index] = 0 then from i := limb_index + 1 until i >= dsize or done loop op.item [dp + i] := op.item [dp + i] + 1 if op.item [dp + i] /= 0 then done := true else i := i + 1 end end if not done then dsize := dsize + 1 op.resize (dsize) op.item [dp + i] := 1 op.count := -dsize end end else p := dp + limb_index x := op.item [p] op.item [p] := x - (1 |<< (bit_index \\ limb_bits)).to_natural_32 if x < (1 |<< (bit_index \\ limb_bits)).to_natural_32 then from p := p + 1 last_p := op.item [p] op.item [p] := last_p - 1 until last_p = 0 loop p := p + 1 last_p := op.item [p] op.item [p] := last_p - 1 end end if op.item [dp + dsize - 1] = 0 then dsize := dsize - 1 end op.count := -dsize end end end bit_test (op: READABLE_INTEGER_X; bit_index: INTEGER): BOOLEAN local u_ptr: SPECIAL [NATURAL_32] size: INTEGER abs_size: INTEGER limb_index: INTEGER p_offset: INTEGER limb: NATURAL_32 do u_ptr := op.item size := op.count abs_size := size.abs limb_index := bit_index // limb_bits p_offset := 0 + limb_index if limb_index >= abs_size then Result := size < 0 else limb := u_ptr [p_offset] if size < 0 then limb := 0 - limb from until p_offset = 0 loop p_offset := p_offset - 1 if u_ptr [p_offset] /= 0 then limb := limb - 1 p_offset := 0 end end end Result := limb.bit_test (bit_index \\ limb_bits) end end bit_xor (res: READABLE_INTEGER_X; op1_a: READABLE_INTEGER_X op2_a: READABLE_INTEGER_X) local op1_ptr: SPECIAL [NATURAL_32] op1_ptr_offset: INTEGER op2_ptr: SPECIAL [NATURAL_32] op2_ptr_offset: INTEGER op1_size: INTEGER op2_size: INTEGER res_ptr: SPECIAL [NATURAL_32] res_ptr_offset: INTEGER res_size: INTEGER res_alloc: INTEGER i: INTEGER opx: SPECIAL [NATURAL_32] opx_offset: INTEGER junk: NATURAL_32 done: BOOLEAN tmp_special: SPECIAL [NATURAL_32] tmp_integer: INTEGER tmp_integer_x: READABLE_INTEGER_X op1: READABLE_INTEGER_X op2: READABLE_INTEGER_X cy: NATURAL_32 carry: CELL [NATURAL_32] do create carry.put (0) op1 := op1_a op2 := op2_a op1_size := op1.count op2_size := op2.count op1_ptr := op1.item op2_ptr := op2.item res_ptr := res.item if op1_size >= 0 then if op2_size >= 0 then res_size := op1_size.max (op2_size) res.resize (res_size) res_ptr := res.item op1_ptr := op1.item op2_ptr := op2.item bit_xor_special (res_ptr, 0, op1_ptr, 0, op1_size, op2_ptr, 0, op2_size) res_size := normalize (res_ptr, res_ptr_offset, res_size) res.count := res_size done := True end else if op2_size < 0 then op1_size := -op1_size op2_size := -op2_size create opx.make_filled (0, op1_size) sub_1 (opx, opx_offset, op1_ptr, op1_ptr_offset, op1_size, 1, carry) junk := carry.item op1_ptr := opx op1_ptr_offset := opx_offset create opx.make_filled (0, op2_size) sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry) junk := carry.item op2_ptr := opx op2_ptr_offset := opx_offset res_alloc := op1_size.max (op2_size) res.resize (res_alloc) res_ptr := res.item if op1_size > op2_size then res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size) from i := op2_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i]) i := i - 1 end res_size := op1_size else res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size) from i := op1_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i]) i := i - 1 end res_size := op2_size end res_size := normalize (res_ptr, res_ptr_offset, res_size) res.count := res_size done := True else tmp_integer_x := op1 op1 := op2 op2 := tmp_integer_x tmp_special := op1_ptr op1_ptr := op2_ptr op2_ptr := tmp_special tmp_integer := op1_ptr_offset op1_ptr_offset := op2_ptr_offset op2_ptr_offset := tmp_integer tmp_integer := op1_size op1_size := op2_size op2_size := tmp_integer end end if not done then op2_size := -op2_size create opx.make_filled (0, op2_size) sub_1 (opx, opx_offset, op2_ptr, op2_ptr_offset, op2_size, 1, carry) junk := carry.item op2_ptr := opx op2_ptr_offset := opx_offset res_alloc := op1_size.max (op2_size) + 1 res.resize (res_alloc) res_ptr := res.item if op1_size > op2_size then res_ptr.copy_data (op1_ptr, op1_ptr_offset + op2_size, res_ptr_offset + op2_size, op1_size - op2_size) from i := op2_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i]) i := i - 1 end res_size := op1_size else res_ptr.copy_data (op2_ptr, op2_ptr_offset + op1_size, res_ptr_offset + op1_size, op2_size - op1_size) from i := op1_size - 1 until i < 0 loop res_ptr [res_ptr_offset + i] := op1_ptr [op1_ptr_offset + i].bit_xor (op2_ptr [op2_ptr_offset + i]) i := i - 1 end res_size := op2_size end add_1 (res_ptr, res_ptr_offset, res_ptr, res_ptr_offset, res_size, 1, carry) cy := carry.item if cy /= 0 then res_ptr [res_ptr_offset + res_size] := cy res_size := res_size + 1 end res_size := normalize (res_ptr, res_ptr_offset, res_size) res.count := - res_size end end bit_xor_lshift (target: READABLE_INTEGER_X; op1: READABLE_INTEGER_X op2_a: READABLE_INTEGER_X left_shift_bits: INTEGER) -- Bit XOR `op1' with (`op2' left shifted `left_shift_bits' bits) local op2: READABLE_INTEGER_X target_special: SPECIAL [NATURAL_32] op1_special: SPECIAL [NATURAL_32] op1_count: INTEGER op2_count: INTEGER target_count_max: INTEGER do if target = op2_a or op1 = op2_a then op2 := op2_a.identity else op2 := op2_a end op1_special := op1.item op1_count := op1.count op2_count := op2.count target_count_max := op1_count + op2_count + bits_to_limbs (left_shift_bits) target.resize (target_count_max) target_special := target.item bit_xor_lshift_special (target_special, 0, op1_special, 0, op1_count, op2.item, 0, op2_count, left_shift_bits) target.count := normalize (target_special, 0, target_count_max) end end