def test_fig23_best_mask(): # ISO/IEC 18004:2015(E) - 7.8.2 Data mask patterns # Figure 23 matrix = read_matrix('fig-23-unmasked') mask, matrix = encoder.find_and_apply_best_mask(matrix, 1, is_micro=False) assert 0 == mask ref_matrix = read_matrix('fig-23-mask-0') assert ref_matrix == matrix
def test_fig23_best_mask(): # ISO/IEC 18004:2015(E) - 7.8.2 Data mask patterns # Figure 23 matrix = read_matrix('fig-23-unmasked') mask = encoder.find_and_apply_best_mask(matrix, 1, is_micro=False) assert 0 == mask ref_matrix = read_matrix('fig-23-mask-0') assert ref_matrix == matrix
def test_encode_single(): # ISO/IEC 18004:2015(E) - page 7 # 'QR Code Symbol' as 1-M symbol seq = segno.make_sequence('QR Code Symbol', version=1, error='M', boost_error=False) assert '1-M' == seq.designator ref_matrix = read_matrix('iso-fig-1') assert ref_matrix == seq.matrix qr = seq[0] assert '1-M' == qr.designator ref_matrix = read_matrix('iso-fig-1') assert ref_matrix == qr.matrix
def test_thonky_add_format_info(): # <http://www.thonky.com/qr-code-tutorial/format-version-information#put-the-format-string-into-the-qr-code> version = 1 matrix = encoder.make_matrix(version, reserve_regions=False) encoder.add_finder_patterns(matrix, is_micro=False) encoder.add_format_info(matrix, version, consts.ERROR_LEVEL_L, 4) ref_matrix = read_matrix('thonky_format') assert ref_matrix == matrix
def test_thonky_add_format_info(): # <http://www.thonky.com/qr-code-tutorial/format-version-information#put-the-format-string-into-the-qr-code> version = 1 matrix = encoder.make_matrix(version, reserve_regions=False) encoder.add_finder_patterns(matrix, is_micro=False) encoder.add_format_info(matrix, version, consts.ERROR_LEVEL_L, 4) ref_matrix = read_matrix('thonky_format') assert ref_matrix == matrix
def test_encode_multi_by_version_or_symbol_count(version, symbol_count): # ISO/IEC 18004:2015(E) - page 60 seq = segno.make_sequence('ABCDEFGHIJKLMN' 'OPQRSTUVWXYZ0123' '456789ABCDEFGHIJ' 'KLMNOPQRSTUVWXYZ', version=version, symbol_count=symbol_count, error='m', mask=4, boost_error=False) assert 4 == len(seq) ref_matrix = read_matrix('seq-iso-04-01') assert ref_matrix == seq[0].matrix ref_matrix = read_matrix('seq-iso-04-02') assert ref_matrix == seq[1].matrix ref_matrix = read_matrix('seq-iso-04-03') assert ref_matrix == seq[2].matrix ref_matrix = read_matrix('seq-iso-04-04') assert ref_matrix == seq[3].matrix
def test_encode_iso_fig1(): # ISO/IEC 18004:2015(E) - page 7 # 'QR Code Symbol' as 1-M symbol qr = encoder.encode('QR Code Symbol', error='M', mask=None, micro=False, boost_error=False) assert consts.ERROR_LEVEL_M == qr.error assert 1 == qr.version assert 5 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) ref_matrix = read_matrix('iso-fig-1') assert ref_matrix == qr.matrix
def test_encode_iso_fig1(): # ISO/IEC 18004:2015(E) - page 7 # 'QR Code Symbol' as 1-M symbol qr = encoder.encode('QR Code Symbol', error='M', mask=None, micro=False, boost_error=False) assert consts.ERROR_LEVEL_M == qr.error assert 1 == qr.version assert 5 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) ref_matrix = read_matrix('iso-fig-1') assert ref_matrix == qr.matrix
def test_encode_iso_fig29(): # ISO/IEC 18004:2015(E) - page 60 # ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ #TODO: If mask is None, Segno chooses mask 3, but the figure uses mask 4... qr = encoder.encode('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', error='m', mask=4, boost_error=False) assert qr.mask == 4 ref_matrix = read_matrix('iso-fig-29') assert ref_matrix == qr.matrix
def test_thonky_add_version_info(): # <http://www.thonky.com/qr-code-tutorial/format-version-information> version = 7 matrix = encoder.make_matrix(version, reserve_regions=False) encoder.add_finder_patterns(matrix, is_micro=False) encoder.add_alignment_patterns(matrix, version) encoder.add_version_info(matrix, version) matrix[-8][8] = 0x1 # dark module ref_matrix = read_matrix('thonky_version') assert ref_matrix == matrix
def test_thonky_pattern_2(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-2') matrix_size = len(matrix) assert 206 == encoder.score_n1(matrix, matrix_size) assert 141 == encoder.score_n2(matrix, matrix_size) # Thonky: 160 assert 800 == encoder.score_n3(matrix, matrix_size) assert 0 == encoder.score_n4(matrix, matrix_size) assert 507 - 160 + 800 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_add_version_info(): # <http://www.thonky.com/qr-code-tutorial/format-version-information> version = 7 matrix = encoder.make_matrix(version, reserve_regions=False) encoder.add_finder_patterns(matrix, is_micro=False) encoder.add_alignment_patterns(matrix, version) encoder.add_version_info(matrix, version) matrix[-8][8] = 0x1 # dark module ref_matrix = read_matrix('thonky_version') assert ref_matrix == matrix
def test_thonky_pattern_7(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-7') matrix_size = len(matrix) assert 197 == encoder.score_n1(matrix, matrix_size) assert 123 == encoder.score_n2(matrix, matrix_size) # Thonky: 200 assert 720 == encoder.score_n3(matrix, matrix_size) assert 0 == encoder.score_n4(matrix, matrix_size) # See score 3 assert 520 - 200 + 720 == encoder.evaluate_mask(matrix, matrix_size)
def test_encode_iso_fig29(): # ISO/IEC 18004:2015(E) - page 60 # ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ # TODO: If mask is None, Segno chooses mask 3, but the figure uses mask 4... qr = encoder.encode('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', error='m', mask=4, boost_error=False) assert 4 == qr.mask assert 4 == qr.version ref_matrix = read_matrix('iso-fig-29') assert ref_matrix == qr.matrix
def test_thonky_pattern_1(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-1') matrix_size = len(matrix) assert 172 == encoder.score_n1(matrix, matrix_size) assert 129 == encoder.score_n2(matrix, matrix_size) # Thonky: 120 assert 760 == encoder.score_n3(matrix, matrix_size) assert 0 == encoder.score_n4(matrix, matrix_size) # See score 3 assert 421 - 120 + 760 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_3(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-3') matrix_size = len(matrix) assert 180 == encoder.score_n1(matrix, matrix_size) assert 141 == encoder.score_n2(matrix, matrix_size) # Thonky: 120 assert 760 == encoder.score_n3(matrix, matrix_size) # Thonky: 2, but that's impossible: Either 0 or a multiple of 10 (N4 = 10) assert 0 == encoder.score_n4(matrix, matrix_size) assert 443 - 2 - 120 + 760 == encoder.evaluate_mask(matrix, matrix_size)
def test_format_info_figure26(): # 7.9.2 Micro QR Code symbols (page 57) version = consts.VERSION_M1 mask = 3 matrix = tuple([bytearray([0x0] * 11) for i in range(11)]) encoder.add_timing_pattern(matrix, is_micro=True) encoder.add_finder_patterns(matrix, is_micro=True) encoder.add_format_info(matrix, version=version, error=None, mask_pattern=mask) ref_matrix = read_matrix('fig-26') assert len(ref_matrix) == len(matrix) assert ref_matrix == matrix
def test_thonky_pattern_0(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-0') matrix_size = len(matrix) assert 180 == encoder.score_n1(matrix, matrix_size) assert 90 == encoder.score_n2(matrix, matrix_size) # Thonky: 80 assert 760 == encoder.score_n3(matrix, matrix_size) assert 0 == encoder.score_n4(matrix, matrix_size) # See score 3 assert 350 - 80 + 760 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_2(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-2') matrix_size = len(matrix) scores = encoder.mask_scores(matrix, matrix_size) assert 206 == scores[0] assert 141 == scores[1] # Thonky: 160 assert 800 == scores[2] assert 0 == scores[3] assert 507 - 160 + 800 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_3(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-3') matrix_size = len(matrix) scores = encoder.mask_scores(matrix, matrix_size) assert 180 == scores[0] assert 141 == scores[1] # Thonky: 120 assert 760 == scores[2] # Thonky: 2, but that's impossible: Either 0 or a multiple of 10 (N4 = 10) assert 0 == scores[3] assert 443 - 2 - 120 + 760 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_1(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-1') matrix_size = len(matrix) scores = encoder.mask_scores(matrix, matrix_size) assert 172 == scores[0] assert 129 == scores[1] # Thonky: 120 assert 760 == scores[2] assert 0 == scores[3] # See score 3 assert 421 - 120 + 760 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_6(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-6') matrix_size = len(matrix) assert 171 == encoder.score_n1(matrix, matrix_size) assert 102 == encoder.score_n2(matrix, matrix_size) # Thonky: 80 assert 840 == encoder.score_n3(matrix, matrix_size) # Thonky: 4, but that's impossible: Either 0 or a multiple of 10 (N4 = 10) assert 0 == encoder.score_n4(matrix, matrix_size) # See score 3 and 4 assert 357 - 4 - 80 + 840 == encoder.evaluate_mask(matrix, matrix_size)
def test_format_info_figure26(): # 7.9.2 Micro QR Code symbols (page 57) version = consts.VERSION_M1 mask = 3 matrix = tuple([bytearray([0x0] * 11) for i in range(11)]) encoder.add_timing_pattern(matrix, is_micro=True) encoder.add_finder_patterns(matrix, is_micro=True) encoder.add_format_info(matrix, version=version, error=None, mask_pattern=mask) ref_matrix = read_matrix('fig-26') assert len(ref_matrix) == len(matrix) assert ref_matrix == matrix
def test_thonky_pattern_7(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-7') matrix_size = len(matrix) scores = encoder.mask_scores(matrix, matrix_size) assert 197 == scores[0] assert 123 == scores[1] # Thonky: 200 assert 720 == scores[2] assert 0 == scores[3] # See score 3 assert 520 - 200 + 720 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_5(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-5') matrix_size = len(matrix) assert 189 == encoder.score_n1(matrix, matrix_size) assert 156 == encoder.score_n2(matrix, matrix_size) # Thonky: 200 assert 800 == encoder.score_n3(matrix, matrix_size) # Thonky: 2, but that's impossible: Either 0 or a multiple of 10 (N4 = 10) assert 0 == encoder.score_n4(matrix, matrix_size) # See score 3 and 4 assert 547 - 2 - 200 + 800 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_5(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-5') matrix_size = len(matrix) scores = encoder.mask_scores(matrix, matrix_size) assert 189 == scores[0] assert 156 == scores[1] # Thonky: 200 assert 800 == scores[2] # Thonky: 2, but that's impossible: Either 0 or a multiple of 10 (N4 = 10) assert 0 == scores[3] # See score 3 and 4 assert 547 - 2 - 200 + 800 == encoder.evaluate_mask(matrix, matrix_size)
def test_thonky_pattern_6(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking_mask-6') matrix_size = len(matrix) scores = encoder.mask_scores(matrix, matrix_size) assert 171 == scores[0] assert 102 == scores[1] # Thonky: 80 assert 840 == scores[2] # Thonky: 4, but that's impossible: Either 0 or a multiple of 10 (N4 = 10) assert 0 == scores[3] # See score 3 and 4 assert 357 - 4 - 80 + 840 == encoder.evaluate_mask(matrix, matrix_size)
def test_figure22_mask3(): # ISO/IEC 18004:2015(E) - 7.8.2 Data mask patterns # Figure 22 - Mask 3 version = consts.VERSION_M4 matrix = _make_figure22_matrix() mask = encoder.find_and_apply_best_mask(matrix, version, True, proposed_mask=3) assert 3 == mask # Format info = dark modules for i in range(9): matrix[8][i] = 0x1 matrix[i][8] = 0x1 ref_matrix = read_matrix('fig-22-mask-3') assert len(ref_matrix) == len(matrix) assert ref_matrix == matrix
def test_covid_cert(): cert_raw = "HC1:6BFOXN*TS0BI$ZD8UH76PCM7ZJ7GZ20II/P3 43JUB/EBUMIU/3%$C2L9KST--M:UC*GPXS40 LHZA KEW%G%9DJ6K1AD1WMN" \ "+I0JK1WLB4DCHGLII3LN25OVLNF7LHCIZ09.9DM*GC9M$7JE9MZIIDOM1JAF.7IFNDXI03L9ZI4Q5%H0AN8EH06YB-TIP+P6OIB.V" \ "T*QNC2BFUF$SU%BO*N5PIBPIAOI-+R2YBV44PZB6H0CJ0QCK0YQK*R3T3+7A.N88J4R$F/MAITH6QS03L0QIRR97I2HOAXL92L0. " \ "KOKGTM8$M8SNCT64RR7+V4YC5/HQRPOHCR6W9.DPEA7IB65C94JB+ONS.CUIA7LE9JAF+B**O3-SY$NRUEG1AK/4C6DM.SY$NWYMG" \ "3GUBRCEIFRMLNKNM8POCJPG8/0NOLZGIZCUOY55*LTUJS1D7.J9$7$.IWQOMJV$6M53AA:6Z2S./BXPHRKGJUHB1WN5LH/M0:3P+E" \ "$$BWWNB8V5ZRF9JMKAX AAOL3H02YF*OF" # Don't use another error correction mode than "M", not sure if this is a requirement, though qr = segno.make(cert_raw, error='m', boost_error=False) assert 'M' == qr.error assert 15 == qr.version ref_matrix = read_matrix('covid-cert') assert ref_matrix assert ref_matrix == qr.matrix
def test_figure22_mask3(): # ISO/IEC 18004:2015(E) - 7.8.2 Data mask patterns # Figure 22 - Mask 3 version = consts.VERSION_M4 matrix = _make_figure22_matrix() mask, matrix = encoder.find_and_apply_best_mask(matrix, version, True, proposed_mask=3) assert 3 == mask # Format info = dark modules for i in range(9): matrix[8][i] = 0x1 matrix[i][8] = 0x1 ref_matrix = read_matrix('fig-22-mask-3') assert len(ref_matrix) == len(matrix) assert ref_matrix == matrix
def test_encode_iso_i3(): # ISO/IEC 18004:2015(E) - page 96 # 01234567 as M2-L symbol qr = encoder.encode('01234567', error='l', version='m2', mask=1, micro=True, boost_error=False) assert consts.ERROR_LEVEL_L == qr.error assert consts.VERSION_M2 == qr.version assert 1 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) qr = encoder.encode('01234567', error='l', version=None, mask=1, micro=True, boost_error=False) assert consts.ERROR_LEVEL_L == qr.error assert consts.VERSION_M2 == qr.version assert 1 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) ref_matrix = read_matrix('iso-i3') assert ref_matrix == qr.matrix
def test_codeword_placement_iso_i3(): # ISO/IEC 18004:2015(E) - page 96 # 01234567 as M2-L symbol s = '01000000 00011000 10101100 11000011 00000000' codewords = Buffer(bits(s)) version = consts.VERSION_M2 buff = encoder.make_final_message(version, consts.ERROR_LEVEL_L, codewords) expected_s = '01000000 00011000 10101100 11000011 00000000 10000110 00001101 00100010 10101110 00110000' expected = bits(expected_s) assert expected == buff.getbits() matrix = encoder.make_matrix(version) encoder.add_finder_patterns(matrix, is_micro=version < 1) encoder.add_codewords(matrix, buff, version=version) ref_matrix = read_matrix('iso-i3_code_placement') assert ref_matrix == matrix
def test_encode_iso_i3(): # ISO/IEC 18004:2015(E) - page 96 # 01234567 as M2-L symbol ref_matrix = read_matrix('iso-i3') qr = encoder.encode('01234567', error='l', version='m2', boost_error=False) assert consts.ERROR_LEVEL_L == qr.error assert consts.VERSION_M2 == qr.version assert 1 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) assert ref_matrix == qr.matrix qr = encoder.encode('01234567', error='l', version=None, micro=True, boost_error=False) assert consts.ERROR_LEVEL_L == qr.error assert consts.VERSION_M2 == qr.version assert 1 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) assert ref_matrix == qr.matrix
def test_codeword_placement_iso_i3(): # ISO/IEC 18004:2015(E) - page 96 # 01234567 as M2-L symbol s = '01000000 00011000 10101100 11000011 00000000' codewords = Buffer(bits(s)).toints() version = consts.VERSION_M2 buff = encoder.make_final_message(version, consts.ERROR_LEVEL_L, codewords) expected_s = '01000000 00011000 10101100 11000011 00000000 10000110 00001101 00100010 10101110 00110000' expected = bits(expected_s) assert expected == buff.getbits() matrix = encoder.make_matrix(version) encoder.add_finder_patterns(matrix, is_micro=version < 1) encoder.add_codewords(matrix, buff, version=version) ref_matrix = read_matrix('iso-i3_code_placement') assert ref_matrix == matrix
def test_encode_iso_i2(): # ISO/IEC 18004:2015(E) - page 94 # 01234567 as 1-M symbol #TODO: Without the mask param Segno chooses mask 3 which seems to be correct # Mask 2 is IMO an error in the standard qr = encoder.encode('01234567', error='m', version=1, mask=2, micro=False, boost_error=False) assert consts.ERROR_LEVEL_M == qr.error assert 1 == qr.version assert 2 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) qr = encoder.encode('01234567', error='m', mask=2, micro=False, boost_error=False) assert consts.ERROR_LEVEL_M == qr.error assert 1 == qr.version assert 2 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) ref_matrix = read_matrix('iso-i2') assert ref_matrix == qr.matrix
def test_encode_iso_i2(): # ISO/IEC 18004:2015(E) - page 94 # 01234567 as 1-M symbol # TODO: Without the mask param Segno chooses mask 3 which seems to be correct # Mask 2 is IMO an error in the standard qr = encoder.encode('01234567', error='m', version=1, mask=2, micro=False, boost_error=False) assert consts.ERROR_LEVEL_M == qr.error assert 1 == qr.version assert 2 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) qr = encoder.encode('01234567', error='m', mask=2, micro=False, boost_error=False) assert consts.ERROR_LEVEL_M == qr.error assert 1 == qr.version assert 2 == qr.mask, 'Wrong mask, got: {0}'.format(qr.mask) ref_matrix = read_matrix('iso-i2') assert ref_matrix == qr.matrix
def test_m3_max_numeric(): qr = segno.make('12345678901234567890123', version='m3', error='l') assert 'M3-L' == qr.designator ref_matrix = read_matrix('issue-33-m3-l-12345678901234567890123') assert ref_matrix == qr.matrix
def make_thonky_score_matrix(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking-1') return matrix, len(matrix)
def test_score_n4(): matrix = read_matrix('thonky_datamasking-2') matrix_size = len(matrix) scores = encoder.mask_scores(matrix, matrix_size) score = scores[3] assert 0 == score
def test_m1_12345(data, version): qr = segno.make(data, version=version) assert 'M1' == qr.designator ref_matrix = read_matrix('issue-33-m1-12345') assert ref_matrix == qr.matrix
def test_score_n4(): matrix = read_matrix('thonky_datamasking-2') score = encoder.score_n4(matrix, len(matrix)) assert 0 == score
def make_thonky_score_matrix(): # http://www.thonky.com/qr-code-tutorial/data-masking matrix = read_matrix('thonky_datamasking-1') return matrix, len(matrix)
def test_eval_micro(): # ISO/IEC 18004:2006(E) page 54 # 6.8.2.2 Evaluation of Micro QR Code symbols matrix = read_matrix('iso_6.8.2.2') res = encoder.evaluate_micro_mask(matrix, len(matrix)) assert 104 == res
def test_jump_from_m3_to_m4_boost_error(): qr = segno.make('123456789012345678901234') assert 'M4-M' == qr.designator ref_matrix = read_matrix('issue-33-m3-l-to-m4-m-jump') assert ref_matrix == qr.matrix
def test_eval_micro(): # ISO/IEC 18004:2006(E) page 54 # 6.8.2.2 Evaluation of Micro QR Code symbols matrix = read_matrix('iso_6.8.2.2') res = encoder.evaluate_micro_mask(matrix, len(matrix)) assert 104 == res
def test_m3_max_numeric(): qr = segno.make('12345678901234567890123', version='m3', error='l') assert 'M3-L' == qr.designator ref_matrix = read_matrix('issue-33-m3-l-12345678901234567890123') assert ref_matrix == qr.matrix
def test_m3_wikipedia(): qr = segno.make('Wikipedia', version='m3', error='l') assert 'M3-L' == qr.designator ref_matrix = read_matrix('issue-33-m3-l-wikipedia') assert ref_matrix == qr.matrix
def test_m3_wikipedia(): qr = segno.make('Wikipedia', version='m3') assert 'M3-L' == qr.designator ref_matrix = read_matrix('issue-33-m3-l-wikipedia') assert ref_matrix == qr.matrix
def test_jump_from_m3_to_m4_boost_error(): qr = segno.make('123456789012345678901234') assert 'M4-M' == qr.designator ref_matrix = read_matrix('issue-33-m3-l-to-m4-m-jump') assert ref_matrix == qr.matrix
def test_m1_12345(data, version): qr = segno.make(data, version=version) assert 'M1' == qr.designator ref_matrix = read_matrix('issue-33-m1-12345') assert ref_matrix == qr.matrix