Fossil SCM
Code and comment cleanup. Fixes to the new formatDiff() routine related to block alignment.
Commit
16a2364f3670205bc4fd8611d15727becaecf725370a902a61f3e6c97d83af44
Parent
5e70c3ff96d97d3…
1 file changed
+45
-52
+45
-52
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -1103,22 +1103,17 @@ | ||
| 1103 | 1103 | ** 1. Delete the next line of pLeft. |
| 1104 | 1104 | ** 2. Insert the next line of pRight. |
| 1105 | 1105 | ** 3. The next line of pLeft changes into the next line of pRight. |
| 1106 | 1106 | ** 4. Delete one line from pLeft and add one line to pRight. |
| 1107 | 1107 | ** |
| 1108 | -** Values larger than three indicate better matches. | |
| 1109 | -** | |
| 1110 | -** The length of the returned array will be just large enough to cause | |
| 1111 | -** all elements of pLeft and pRight to be consumed. | |
| 1112 | -** | |
| 1113 | 1108 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| 1114 | 1109 | ** adding a cost to each match based on how well the two rows match |
| 1115 | 1110 | ** each other. Insertion and deletion costs are 50. Match costs |
| 1116 | 1111 | ** are between 0 and 100 where 0 is a perfect match 100 is a complete |
| 1117 | 1112 | ** mismatch. |
| 1118 | 1113 | */ |
| 1119 | -static unsigned char *sbsAlignment( | |
| 1114 | +static unsigned char *diffBlockAlignment( | |
| 1120 | 1115 | const DLine *aLeft, int nLeft, /* Text on the left */ |
| 1121 | 1116 | const DLine *aRight, int nRight, /* Text on the right */ |
| 1122 | 1117 | u64 diffFlags /* Flags passed into the original diff */ |
| 1123 | 1118 | ){ |
| 1124 | 1119 | int i, j, k; /* Loop counters */ |
| @@ -1128,24 +1123,26 @@ | ||
| 1128 | 1123 | int nMatch, iMatch; /* Number of matching lines and match score */ |
| 1129 | 1124 | int mnLen; /* MIN(nLeft, nRight) */ |
| 1130 | 1125 | int mxLen; /* MAX(nLeft, nRight) */ |
| 1131 | 1126 | int aBuf[100]; /* Stack space for a[] if nRight not to big */ |
| 1132 | 1127 | |
| 1133 | - aM = fossil_malloc( (nLeft+1)*(nRight+1) ); | |
| 1134 | 1128 | if( nLeft==0 ){ |
| 1129 | + aM = fossil_malloc( nLeft + nRight + 2 ); | |
| 1135 | 1130 | memset(aM, 2, nRight); |
| 1136 | 1131 | return aM; |
| 1137 | 1132 | } |
| 1138 | 1133 | if( nRight==0 ){ |
| 1134 | + aM = fossil_malloc( nLeft + nRight + 2 ); | |
| 1139 | 1135 | memset(aM, 1, nLeft); |
| 1140 | 1136 | return aM; |
| 1141 | 1137 | } |
| 1142 | 1138 | |
| 1143 | 1139 | /* This algorithm is O(N**2). So if N is too big, bail out with a |
| 1144 | 1140 | ** simple (but stupid and ugly) result that doesn't take too long. */ |
| 1145 | 1141 | mnLen = nLeft<nRight ? nLeft : nRight; |
| 1146 | 1142 | if( nLeft*nRight>100000 && (diffFlags & DIFF_SLOW_SBS)==0 ){ |
| 1143 | + aM = fossil_malloc( nLeft + nRight + 2 ); | |
| 1147 | 1144 | memset(aM, 4, mnLen); |
| 1148 | 1145 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1149 | 1146 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1150 | 1147 | return aM; |
| 1151 | 1148 | } |
| @@ -1154,10 +1151,12 @@ | ||
| 1154 | 1151 | pToFree = 0; |
| 1155 | 1152 | a = aBuf; |
| 1156 | 1153 | }else{ |
| 1157 | 1154 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1158 | 1155 | } |
| 1156 | + aM = fossil_malloc( (nLeft+1)*(nRight+1) ); | |
| 1157 | + | |
| 1159 | 1158 | |
| 1160 | 1159 | /* Compute the best alignment */ |
| 1161 | 1160 | for(i=0; i<=nRight; i++){ |
| 1162 | 1161 | aM[i] = 2; |
| 1163 | 1162 | a[i] = i*50; |
| @@ -1235,22 +1234,10 @@ | ||
| 1235 | 1234 | /* Return the result */ |
| 1236 | 1235 | fossil_free(pToFree); |
| 1237 | 1236 | return aM; |
| 1238 | 1237 | } |
| 1239 | 1238 | |
| 1240 | -#if 0 /* not used */ | |
| 1241 | -/* | |
| 1242 | -** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a | |
| 1243 | -** pair of adjacent differences. Return true if the gap between these | |
| 1244 | -** two differences is so small that they should be rendered as a single | |
| 1245 | -** edit. | |
| 1246 | -*/ | |
| 1247 | -static int smallGap(int *R){ | |
| 1248 | - return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8; | |
| 1249 | -} | |
| 1250 | -#endif | |
| 1251 | - | |
| 1252 | 1239 | /* |
| 1253 | 1240 | ** Given a diff context in which the aEdit[] array has been filled |
| 1254 | 1241 | ** in, compute a side-by-side diff into pOut. |
| 1255 | 1242 | */ |
| 1256 | 1243 | static void sbsDiff( |
| @@ -1399,23 +1386,11 @@ | ||
| 1399 | 1386 | for(i=0; i<nr; i++){ |
| 1400 | 1387 | unsigned char *alignment; |
| 1401 | 1388 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1402 | 1389 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1403 | 1390 | |
| 1404 | -#if 0 /* not used */ | |
| 1405 | - /* If the gap between the current diff and then next diff within the | |
| 1406 | - ** same block is not too great, then render them as if they are a | |
| 1407 | - ** single diff. */ | |
| 1408 | - while( i<nr-1 && smallGap(&R[r+i*3]) ){ | |
| 1409 | - i++; | |
| 1410 | - m = R[r+i*3]; | |
| 1411 | - ma += R[r+i*3+1] + m; | |
| 1412 | - mb += R[r+i*3+2] + m; | |
| 1413 | - } | |
| 1414 | -#endif | |
| 1415 | - | |
| 1416 | - alignment = sbsAlignment(&A[a], ma, &B[b], mb, diffFlags); | |
| 1391 | + alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); | |
| 1417 | 1392 | for(j=0; ma+mb>0; j++){ |
| 1418 | 1393 | if( alignment[j]==1 ){ |
| 1419 | 1394 | /* Delete one line from the left */ |
| 1420 | 1395 | sbsWriteLineno(&s, a, SBS_LNA); |
| 1421 | 1396 | s.a[0].iStart = 0; |
| @@ -1684,31 +1659,49 @@ | ||
| 1684 | 1659 | for(i=0; i<nr; i++){ |
| 1685 | 1660 | unsigned char *alignment; |
| 1686 | 1661 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1687 | 1662 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1688 | 1663 | |
| 1689 | - alignment = sbsAlignment(&A[a], ma, &B[b], mb, diffFlags); | |
| 1664 | + alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); | |
| 1690 | 1665 | for(j=0; ma+mb>0; j++){ |
| 1691 | - if( alignment[j]==1 ){ | |
| 1692 | - /* Delete one line from the left */ | |
| 1693 | - pBuilder->xDelete(pBuilder, &A[a]); | |
| 1694 | - ma--; | |
| 1695 | - a++; | |
| 1696 | - }else if( alignment[j]==2 ){ | |
| 1697 | - /* Insert one line on the right */ | |
| 1698 | - pBuilder->xInsert(pBuilder, &B[b]); | |
| 1699 | - assert( mb>0 ); | |
| 1700 | - mb--; | |
| 1701 | - b++; | |
| 1702 | - }else{ | |
| 1703 | - /* The left line is changed into the right line */ | |
| 1704 | - pBuilder->xEdit(pBuilder, &A[a], &B[b]); | |
| 1705 | - assert( ma>0 && mb>0 ); | |
| 1706 | - ma--; | |
| 1707 | - mb--; | |
| 1708 | - a++; | |
| 1709 | - b++; | |
| 1666 | + switch( alignment[j] ){ | |
| 1667 | + case 1: { | |
| 1668 | + /* Delete one line from the left */ | |
| 1669 | + pBuilder->xDelete(pBuilder, &A[a]); | |
| 1670 | + ma--; | |
| 1671 | + a++; | |
| 1672 | + break; | |
| 1673 | + } | |
| 1674 | + case 2: { | |
| 1675 | + /* Insert one line on the right */ | |
| 1676 | + pBuilder->xInsert(pBuilder, &B[b]); | |
| 1677 | + assert( mb>0 ); | |
| 1678 | + mb--; | |
| 1679 | + b++; | |
| 1680 | + break; | |
| 1681 | + } | |
| 1682 | + case 3: { | |
| 1683 | + /* The left line is changed into the right line */ | |
| 1684 | + pBuilder->xEdit(pBuilder, &A[a], &B[b]); | |
| 1685 | + assert( ma>0 && mb>0 ); | |
| 1686 | + ma--; | |
| 1687 | + mb--; | |
| 1688 | + a++; | |
| 1689 | + b++; | |
| 1690 | + break; | |
| 1691 | + } | |
| 1692 | + case 4: { | |
| 1693 | + /* Delete from left then separately insert on the right */ | |
| 1694 | + pBuilder->xDelete(pBuilder, &A[a]); | |
| 1695 | + ma--; | |
| 1696 | + a++; | |
| 1697 | + pBuilder->xInsert(pBuilder, &B[b]); | |
| 1698 | + assert( mb>0 ); | |
| 1699 | + mb--; | |
| 1700 | + b++; | |
| 1701 | + break; | |
| 1702 | + } | |
| 1710 | 1703 | } |
| 1711 | 1704 | } |
| 1712 | 1705 | fossil_free(alignment); |
| 1713 | 1706 | if( i<nr-1 ){ |
| 1714 | 1707 | m = R[r+i*3+3]; |
| 1715 | 1708 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -1103,22 +1103,17 @@ | |
| 1103 | ** 1. Delete the next line of pLeft. |
| 1104 | ** 2. Insert the next line of pRight. |
| 1105 | ** 3. The next line of pLeft changes into the next line of pRight. |
| 1106 | ** 4. Delete one line from pLeft and add one line to pRight. |
| 1107 | ** |
| 1108 | ** Values larger than three indicate better matches. |
| 1109 | ** |
| 1110 | ** The length of the returned array will be just large enough to cause |
| 1111 | ** all elements of pLeft and pRight to be consumed. |
| 1112 | ** |
| 1113 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| 1114 | ** adding a cost to each match based on how well the two rows match |
| 1115 | ** each other. Insertion and deletion costs are 50. Match costs |
| 1116 | ** are between 0 and 100 where 0 is a perfect match 100 is a complete |
| 1117 | ** mismatch. |
| 1118 | */ |
| 1119 | static unsigned char *sbsAlignment( |
| 1120 | const DLine *aLeft, int nLeft, /* Text on the left */ |
| 1121 | const DLine *aRight, int nRight, /* Text on the right */ |
| 1122 | u64 diffFlags /* Flags passed into the original diff */ |
| 1123 | ){ |
| 1124 | int i, j, k; /* Loop counters */ |
| @@ -1128,24 +1123,26 @@ | |
| 1128 | int nMatch, iMatch; /* Number of matching lines and match score */ |
| 1129 | int mnLen; /* MIN(nLeft, nRight) */ |
| 1130 | int mxLen; /* MAX(nLeft, nRight) */ |
| 1131 | int aBuf[100]; /* Stack space for a[] if nRight not to big */ |
| 1132 | |
| 1133 | aM = fossil_malloc( (nLeft+1)*(nRight+1) ); |
| 1134 | if( nLeft==0 ){ |
| 1135 | memset(aM, 2, nRight); |
| 1136 | return aM; |
| 1137 | } |
| 1138 | if( nRight==0 ){ |
| 1139 | memset(aM, 1, nLeft); |
| 1140 | return aM; |
| 1141 | } |
| 1142 | |
| 1143 | /* This algorithm is O(N**2). So if N is too big, bail out with a |
| 1144 | ** simple (but stupid and ugly) result that doesn't take too long. */ |
| 1145 | mnLen = nLeft<nRight ? nLeft : nRight; |
| 1146 | if( nLeft*nRight>100000 && (diffFlags & DIFF_SLOW_SBS)==0 ){ |
| 1147 | memset(aM, 4, mnLen); |
| 1148 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1149 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1150 | return aM; |
| 1151 | } |
| @@ -1154,10 +1151,12 @@ | |
| 1154 | pToFree = 0; |
| 1155 | a = aBuf; |
| 1156 | }else{ |
| 1157 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1158 | } |
| 1159 | |
| 1160 | /* Compute the best alignment */ |
| 1161 | for(i=0; i<=nRight; i++){ |
| 1162 | aM[i] = 2; |
| 1163 | a[i] = i*50; |
| @@ -1235,22 +1234,10 @@ | |
| 1235 | /* Return the result */ |
| 1236 | fossil_free(pToFree); |
| 1237 | return aM; |
| 1238 | } |
| 1239 | |
| 1240 | #if 0 /* not used */ |
| 1241 | /* |
| 1242 | ** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a |
| 1243 | ** pair of adjacent differences. Return true if the gap between these |
| 1244 | ** two differences is so small that they should be rendered as a single |
| 1245 | ** edit. |
| 1246 | */ |
| 1247 | static int smallGap(int *R){ |
| 1248 | return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8; |
| 1249 | } |
| 1250 | #endif |
| 1251 | |
| 1252 | /* |
| 1253 | ** Given a diff context in which the aEdit[] array has been filled |
| 1254 | ** in, compute a side-by-side diff into pOut. |
| 1255 | */ |
| 1256 | static void sbsDiff( |
| @@ -1399,23 +1386,11 @@ | |
| 1399 | for(i=0; i<nr; i++){ |
| 1400 | unsigned char *alignment; |
| 1401 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1402 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1403 | |
| 1404 | #if 0 /* not used */ |
| 1405 | /* If the gap between the current diff and then next diff within the |
| 1406 | ** same block is not too great, then render them as if they are a |
| 1407 | ** single diff. */ |
| 1408 | while( i<nr-1 && smallGap(&R[r+i*3]) ){ |
| 1409 | i++; |
| 1410 | m = R[r+i*3]; |
| 1411 | ma += R[r+i*3+1] + m; |
| 1412 | mb += R[r+i*3+2] + m; |
| 1413 | } |
| 1414 | #endif |
| 1415 | |
| 1416 | alignment = sbsAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1417 | for(j=0; ma+mb>0; j++){ |
| 1418 | if( alignment[j]==1 ){ |
| 1419 | /* Delete one line from the left */ |
| 1420 | sbsWriteLineno(&s, a, SBS_LNA); |
| 1421 | s.a[0].iStart = 0; |
| @@ -1684,31 +1659,49 @@ | |
| 1684 | for(i=0; i<nr; i++){ |
| 1685 | unsigned char *alignment; |
| 1686 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1687 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1688 | |
| 1689 | alignment = sbsAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1690 | for(j=0; ma+mb>0; j++){ |
| 1691 | if( alignment[j]==1 ){ |
| 1692 | /* Delete one line from the left */ |
| 1693 | pBuilder->xDelete(pBuilder, &A[a]); |
| 1694 | ma--; |
| 1695 | a++; |
| 1696 | }else if( alignment[j]==2 ){ |
| 1697 | /* Insert one line on the right */ |
| 1698 | pBuilder->xInsert(pBuilder, &B[b]); |
| 1699 | assert( mb>0 ); |
| 1700 | mb--; |
| 1701 | b++; |
| 1702 | }else{ |
| 1703 | /* The left line is changed into the right line */ |
| 1704 | pBuilder->xEdit(pBuilder, &A[a], &B[b]); |
| 1705 | assert( ma>0 && mb>0 ); |
| 1706 | ma--; |
| 1707 | mb--; |
| 1708 | a++; |
| 1709 | b++; |
| 1710 | } |
| 1711 | } |
| 1712 | fossil_free(alignment); |
| 1713 | if( i<nr-1 ){ |
| 1714 | m = R[r+i*3+3]; |
| 1715 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -1103,22 +1103,17 @@ | |
| 1103 | ** 1. Delete the next line of pLeft. |
| 1104 | ** 2. Insert the next line of pRight. |
| 1105 | ** 3. The next line of pLeft changes into the next line of pRight. |
| 1106 | ** 4. Delete one line from pLeft and add one line to pRight. |
| 1107 | ** |
| 1108 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| 1109 | ** adding a cost to each match based on how well the two rows match |
| 1110 | ** each other. Insertion and deletion costs are 50. Match costs |
| 1111 | ** are between 0 and 100 where 0 is a perfect match 100 is a complete |
| 1112 | ** mismatch. |
| 1113 | */ |
| 1114 | static unsigned char *diffBlockAlignment( |
| 1115 | const DLine *aLeft, int nLeft, /* Text on the left */ |
| 1116 | const DLine *aRight, int nRight, /* Text on the right */ |
| 1117 | u64 diffFlags /* Flags passed into the original diff */ |
| 1118 | ){ |
| 1119 | int i, j, k; /* Loop counters */ |
| @@ -1128,24 +1123,26 @@ | |
| 1123 | int nMatch, iMatch; /* Number of matching lines and match score */ |
| 1124 | int mnLen; /* MIN(nLeft, nRight) */ |
| 1125 | int mxLen; /* MAX(nLeft, nRight) */ |
| 1126 | int aBuf[100]; /* Stack space for a[] if nRight not to big */ |
| 1127 | |
| 1128 | if( nLeft==0 ){ |
| 1129 | aM = fossil_malloc( nLeft + nRight + 2 ); |
| 1130 | memset(aM, 2, nRight); |
| 1131 | return aM; |
| 1132 | } |
| 1133 | if( nRight==0 ){ |
| 1134 | aM = fossil_malloc( nLeft + nRight + 2 ); |
| 1135 | memset(aM, 1, nLeft); |
| 1136 | return aM; |
| 1137 | } |
| 1138 | |
| 1139 | /* This algorithm is O(N**2). So if N is too big, bail out with a |
| 1140 | ** simple (but stupid and ugly) result that doesn't take too long. */ |
| 1141 | mnLen = nLeft<nRight ? nLeft : nRight; |
| 1142 | if( nLeft*nRight>100000 && (diffFlags & DIFF_SLOW_SBS)==0 ){ |
| 1143 | aM = fossil_malloc( nLeft + nRight + 2 ); |
| 1144 | memset(aM, 4, mnLen); |
| 1145 | if( nLeft>mnLen ) memset(aM+mnLen, 1, nLeft-mnLen); |
| 1146 | if( nRight>mnLen ) memset(aM+mnLen, 2, nRight-mnLen); |
| 1147 | return aM; |
| 1148 | } |
| @@ -1154,10 +1151,12 @@ | |
| 1151 | pToFree = 0; |
| 1152 | a = aBuf; |
| 1153 | }else{ |
| 1154 | a = pToFree = fossil_malloc( sizeof(a[0])*(nRight+1) ); |
| 1155 | } |
| 1156 | aM = fossil_malloc( (nLeft+1)*(nRight+1) ); |
| 1157 | |
| 1158 | |
| 1159 | /* Compute the best alignment */ |
| 1160 | for(i=0; i<=nRight; i++){ |
| 1161 | aM[i] = 2; |
| 1162 | a[i] = i*50; |
| @@ -1235,22 +1234,10 @@ | |
| 1234 | /* Return the result */ |
| 1235 | fossil_free(pToFree); |
| 1236 | return aM; |
| 1237 | } |
| 1238 | |
| 1239 | /* |
| 1240 | ** Given a diff context in which the aEdit[] array has been filled |
| 1241 | ** in, compute a side-by-side diff into pOut. |
| 1242 | */ |
| 1243 | static void sbsDiff( |
| @@ -1399,23 +1386,11 @@ | |
| 1386 | for(i=0; i<nr; i++){ |
| 1387 | unsigned char *alignment; |
| 1388 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1389 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1390 | |
| 1391 | alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1392 | for(j=0; ma+mb>0; j++){ |
| 1393 | if( alignment[j]==1 ){ |
| 1394 | /* Delete one line from the left */ |
| 1395 | sbsWriteLineno(&s, a, SBS_LNA); |
| 1396 | s.a[0].iStart = 0; |
| @@ -1684,31 +1659,49 @@ | |
| 1659 | for(i=0; i<nr; i++){ |
| 1660 | unsigned char *alignment; |
| 1661 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1662 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1663 | |
| 1664 | alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1665 | for(j=0; ma+mb>0; j++){ |
| 1666 | switch( alignment[j] ){ |
| 1667 | case 1: { |
| 1668 | /* Delete one line from the left */ |
| 1669 | pBuilder->xDelete(pBuilder, &A[a]); |
| 1670 | ma--; |
| 1671 | a++; |
| 1672 | break; |
| 1673 | } |
| 1674 | case 2: { |
| 1675 | /* Insert one line on the right */ |
| 1676 | pBuilder->xInsert(pBuilder, &B[b]); |
| 1677 | assert( mb>0 ); |
| 1678 | mb--; |
| 1679 | b++; |
| 1680 | break; |
| 1681 | } |
| 1682 | case 3: { |
| 1683 | /* The left line is changed into the right line */ |
| 1684 | pBuilder->xEdit(pBuilder, &A[a], &B[b]); |
| 1685 | assert( ma>0 && mb>0 ); |
| 1686 | ma--; |
| 1687 | mb--; |
| 1688 | a++; |
| 1689 | b++; |
| 1690 | break; |
| 1691 | } |
| 1692 | case 4: { |
| 1693 | /* Delete from left then separately insert on the right */ |
| 1694 | pBuilder->xDelete(pBuilder, &A[a]); |
| 1695 | ma--; |
| 1696 | a++; |
| 1697 | pBuilder->xInsert(pBuilder, &B[b]); |
| 1698 | assert( mb>0 ); |
| 1699 | mb--; |
| 1700 | b++; |
| 1701 | break; |
| 1702 | } |
| 1703 | } |
| 1704 | } |
| 1705 | fossil_free(alignment); |
| 1706 | if( i<nr-1 ){ |
| 1707 | m = R[r+i*3+3]; |
| 1708 |