trevc(3)
πΈ trevc β eigenvectors of triangular Schur form, old π
okay so bestie, first things first: this is trevc from Library Functions Manual, section 3. she's old. the name literally says "old" β that's not me being shady, that's the actual NAME line. we're looking at the legacy LAPACK-era routine here, and there are four flavours of her: ctrevc, dtrevc, strevc, ztrevc. buckle up π
β¨ NAME β¨
trevc β trevc: eigenvectors of triangular Schur form, old
like I said. old. iconic, but old. π
β¨ SYNOPSIS β¨
π Functions π
subroutine ctrevc (side, howmny, select, n, t, ldt, vl, ldvl, vr, ldvr, mm, m, work, rwork, info)β CTREVCsubroutine dtrevc (side, howmny, select, n, t, ldt, vl, ldvl, vr, ldvr, mm, m, work, info)β DTREVCsubroutine strevc (side, howmny, select, n, t, ldt, vl, ldvl, vr, ldvr, mm, m, work, info)β STREVCsubroutine ztrevc (side, howmny, select, n, t, ldt, vl, ldvl, vr, ldvr, mm, m, work, rwork, info)β ZTREVC
notice how ctrevc and ztrevc get an extra rwork and the real ones don't? that's not a typo, that's just how she is πββοΈ
β¨ Detailed Description β¨
it's giving "reference documentation with no chill." scroll down for the good stuff π«Ά
β¨ Function Documentation β¨
π¦ subroutine ctrevc π¦
subroutine ctrevc (character side, character howmny, logical, dimension( * )
select, integer n, complex, dimension( ldt, * ) t, integer ldt, complex,
dimension( ldvl, * ) vl, integer ldvl, complex, dimension( ldvr, * ) vr,
integer ldvr, integer mm, integer m, complex, dimension( * ) work, real,
dimension( * ) rwork, integer info)
CTREVC
π― Purpose:
okay so CTREVC computes some or all of the right and/or left eigenvectors of a complex upper triangular matrix T. and where do these come from? matrices of this type are produced by the Schur factorization of a complex general matrix:
A = Q*T*Q**H
as computed by CHSEQR. slay.
bestie, here's the definition. the right eigenvector x and the left eigenvector y of T corresponding to an eigenvalue w are defined by:
T*x = w*x, (y**H)*T = w*(y**H)
where y**H denotes the conjugate transpose of the vector y. π§
and the eigenvalues? not input to this routine β they're read directly from the diagonal of T. she reads the room, she doesn't get told. π
this routine returns the matrices X and/or Y of right and left eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an input matrix. and if Q is the unitary factor that reduces a matrix A to Schur form T, then Q*X and Q*Y are the matrices of right and left eigenvectors of A. no cap, that's the whole vibe.
πΈ Parameters
SIDEβSIDEisCHARACTER*1. so many choices, bestie:= 'R': compute right eigenvectors only;= 'L': compute left eigenvectors only;= 'B': compute both right and left eigenvectors.
HOWMNYβHOWMNYisCHARACTER*1. this one's the "how do you want 'em" dial:= 'A': compute all right and/or left eigenvectors;= 'B': compute all right and/or left eigenvectors, backtransformed using the matrices supplied inVRand/orVL;= 'S': compute selected right and/or left eigenvectors, as indicated by the logical arraySELECT.
SELECTβSELECTis aLOGICALarray, dimension(N). ifHOWMNY = 'S', thenSELECTspecifies the eigenvectors to be computed. the eigenvector corresponding to the j-th eigenvalue is computed ifSELECT(j) = .TRUE.. not referenced ifHOWMNY = 'A'or'B'β she simply doesn't look at it, don't take it personally πNβNisINTEGER. the order of the matrixT.N >= 0.TβTis aCOMPLEXarray, dimension(LDT,N). the upper triangular matrixT. β οΈTis modified, but restored on exit β so she rummages through your closet and puts everything back exactly where she found it. π«ΆLDTβLDTisINTEGER. the leading dimension of the arrayT.LDT >= max(1,N).VLβVLis aCOMPLEXarray, dimension(LDVL,MM).- on entry, if
SIDE = 'L'or'B'andHOWMNY = 'B',VLmust contain anN-by-NmatrixQ(usually the unitary matrixQof Schur vectors returned byCHSEQR). - on exit, if
SIDE = 'L'or'B',VLcontains:- if
HOWMNY = 'A', the matrixYof left eigenvectors ofT; - if
HOWMNY = 'B', the matrixQ*Y; - if
HOWMNY = 'S', the left eigenvectors ofTspecified bySELECT, stored consecutively in the columns ofVL, in the same order as their eigenvalues.
- if
- not referenced if
SIDE = 'R'.
- on entry, if
LDVLβLDVLisINTEGER. the leading dimension of the arrayVL.LDVL >= 1, and ifSIDE = 'L'or'B',LDVL >= N.VRβVRis aCOMPLEXarray, dimension(LDVR,MM).- on entry, if
SIDE = 'R'or'B'andHOWMNY = 'B',VRmust contain anN-by-NmatrixQ(usually the unitary matrixQof Schur vectors returned byCHSEQR). - on exit, if
SIDE = 'R'or'B',VRcontains:- if
HOWMNY = 'A', the matrixXof right eigenvectors ofT; - if
HOWMNY = 'B', the matrixQ*X; - if
HOWMNY = 'S', the right eigenvectors ofTspecified bySELECT, stored consecutively in the columns ofVR, in the same order as their eigenvalues.
- if
- not referenced if
SIDE = 'L'.
- on entry, if
LDVRβLDVRisINTEGER. the leading dimension of the arrayVR.LDVR >= 1, and ifSIDE = 'R'or'B';LDVR >= N. (yes, that semicolon is in the original, she's quirky like that π)MMβMMisINTEGER. the number of columns in the arraysVLand/orVR.MM >= M.MβMisINTEGER. the number of columns in the arraysVLand/orVRactually used to store the eigenvectors. ifHOWMNY = 'A'or'B',Mis set toN. each selected eigenvector occupies one column. one girl, one column, periodt. β¨WORKβWORKis aCOMPLEXarray, dimension(2*N). that's right, two timesN, don't skimp.RWORKβRWORKis aREALarray, dimension(N).INFOβINFOisINTEGER:= 0: successful exit π< 0: ifINFO = -i, the i-th argument had an illegal value. so if you seeINFO = -3, bestie, argument 3 is the problem and she's calling it out π
π Author
- Univ. of Tennessee
- Univ. of California Berkeley
- Univ. of Colorado Denver
- NAG Ltd.
the whole group chat contributed, honestly.
π₯ Further Details:
- the algorithm used in this program is basically backward (forward) substitution, with scaling to make the the code robust against possible overflow. (yes, "the the" β she said it twice, we're leaving it, it's part of the lore π )
- each eigenvector is normalized so that the element of largest magnitude has magnitude
1; here the magnitude of a complex number(x,y)is taken to be|x| + |y|.
that's not a typo either β |x| + |y|, not the usual square-root situation. she does her own thing and honestly? it works. β
Definition at line 216 of file ctrevc.f.
π§ subroutine dtrevc π§
subroutine dtrevc (character side, character howmny, logical, dimension( * )
select, integer n, double precision, dimension( ldt, * ) t, integer ldt,
double precision, dimension( ldvl, * ) vl, integer ldvl, double
precision, dimension( ldvr, * ) vr, integer ldvr, integer mm, integer m,
double precision, dimension( * ) work, integer info)
DTREVC
π― Purpose:
DTREVC computes some or all of the right and/or left eigenvectors of a real upper quasi-triangular matrix T. yes β quasi-triangular, she's got 2Γ2 blocks on the diagonal, it's a whole thing. π
matrices of this type are produced by the Schur factorization of a real general matrix:
A = Q*T*Q**T
as computed by DHSEQR. note the Q**T, not Q**H β real girl behaviour.
the right eigenvector x and the left eigenvector y of T corresponding to an eigenvalue w are defined by:
T*x = w*x, (y**H)*T = w*(y**H)
where y**H denotes the conjugate transpose of y. π¦
the eigenvalues are not input to this routine, but are read directly from the diagonal blocks of T.
this routine returns the matrices X and/or Y of right and left eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an input matrix. if Q is the orthogonal factor that reduces a matrix A to Schur form T, then Q*X and Q*Y are the matrices of right and left eigenvectors of A. (unitary in the complex version, orthogonal here β she's not swapping those, okay? π)
πΈ Parameters
SIDEβSIDEisCHARACTER*1:= 'R': compute right eigenvectors only;= 'L': compute left eigenvectors only;= 'B': compute both right and left eigenvectors.
HOWMNYβHOWMNYisCHARACTER*1:= 'A': compute all right and/or left eigenvectors;= 'B': compute all right and/or left eigenvectors, backtransformed by the matrices inVRand/orVL;= 'S': compute selected right and/or left eigenvectors, as indicated by the logical arraySELECT.
SELECTβSELECTis aLOGICALarray, dimension(N). ifHOWMNY = 'S',SELECTspecifies the eigenvectors to be computed. but here's the extra lore for the real version, bestie, pay attention: π¨- if
w(j)is a real eigenvalue, the corresponding real eigenvector is computed ifSELECT(j)is.TRUE.. - if
w(j)andw(j+1)are the real and imaginary parts of a complex eigenvalue, the corresponding complex eigenvector is computed if eitherSELECT(j)orSELECT(j+1)is.TRUE., and on exitSELECT(j)is set to.TRUE.andSELECT(j+1)is set to.FALSE.. she picks a winner and it'sj. main character energy. π - not referenced if
HOWMNY = 'A'or'B'.
- if
NβNisINTEGER. the order of the matrixT.N >= 0.TβTis aDOUBLE PRECISIONarray, dimension(LDT,N). the upper quasi-triangular matrixTin Schur canonical form.LDTβLDTisINTEGER. the leading dimension of the arrayT.LDT >= max(1,N).VLβ (okay bestie this is exactly where part 1 runs out π the tea onVLcontinues in the next part π )VLβDOUBLE PRECISIONarray, dimension(LDVL,MM). Ok so picture this: on entry, ifSIDE = 'L'or'B'andHOWMNY = 'B', thenVLhas to already contain an N-by-N matrix Q (usually the orthogonal matrix Q of Schur vectors thatDHSEQRhanded back to you). On exit, ifSIDE = 'L'or'B',VLcontains:- if
HOWMNY = 'A', the matrix Y of left eigenvectors of T; - if
HOWMNY = 'B', the matrix Q*Y; - if
HOWMNY = 'S', the left eigenvectors of T specified bySELECT, stored consecutively in the columns ofVL, in the same order as their eigenvalues.
- if
A complex eigenvector corresponding to a complex eigenvalue is stored in two consecutive columns β first column = the real part, second = the imaginary part. Two slots, one vibe π
Not referenced if SIDE = 'R'.
LDVLβINTEGER. The leading dimension of the arrayVL.LDVL >= 1, and ifSIDE = 'L'or'B', thenLDVL >= N. Gen Z translation: don't lowball this number, the Fortran will not forgive you π«ΆVRβDOUBLE PRECISIONarray, dimension(LDVR,MM). On entry, ifSIDE = 'R'or'B'andHOWMNY = 'B',VRmust contain an N-by-N matrix Q (usually the orthogonal matrix Q of Schur vectors returned byDHSEQR). On exit, ifSIDE = 'R'or'B',VRcontains:- if
HOWMNY = 'A', the matrix X of right eigenvectors of T; - if
HOWMNY = 'B', the matrix Q*X; - if
HOWMNY = 'S', the right eigenvectors of T specified bySELECT, stored consecutively in the columns ofVR, in the same order as their eigenvalues.
- if
A complex eigenvector corresponding to a complex eigenvalue is stored in two consecutive columns β first column holds the real part and the second the imaginary part. Not referenced if SIDE = 'L'. Yes bestie, VL and VR are literally the same paragraph with the letters swapped. Iconic symmetry, no notes β¨
LDVRβINTEGER. The leading dimension of the arrayVR.LDVR >= 1, and ifSIDE = 'R'or'B', thenLDVR >= N.MMβINTEGER. The number of columns in the arraysVLand/orVR.MM >= M. You bring the venue size, the routine tells you how many eigenvectors actually showed up πMβINTEGER. The number of columns in the arraysVLand/orVRthat are actually used to store the eigenvectors. IfHOWMNY = 'A'or'B',Mis set toN. Each selected real eigenvector occupies one column and each selected complex eigenvector occupies two columns. Complex ones take up two seats, fr fr πWORKβDOUBLE PRECISIONarray, dimension(3*N). Scratch space, don't touch it, it's doing its job π§INFOβINTEGER. The receipts:= 0: successful exit π< 0: ifINFO = -i, thei-th argument had an illegal value somebody passed something cursed, go check argument number-INFOπ
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.
Further Details:
The algorithm used in this program is basically backward (forward) substitution, with scaling to make the the code robust against possible overflow. (Yes, "the the" is in the source. We are leaving it exactly as-is, because accuracy is the assignment π )
Each eigenvector is normalized so that the element of largest magnitude has magnitude 1; here the magnitude of a complex number (x,y) is taken to be |x| + |y|. That's the 1-norm vibe check, not the fancy Euclidean one β noted, memorized, moving on β¨
Definition at line 220 of file dtrevc.f.
π¦ and nowβ¦ the single-precision sibling: strevc π¦
subroutine strevc (character side, character howmny, logical, dimension( * )
select, integer n, real, dimension( ldt, * ) t, integer ldt, real,
dimension( ldvl, * ) vl, integer ldvl, real, dimension( ldvr, * ) vr,
integer ldvr, integer mm, integer m, real, dimension( * ) work, integer
info)
STREVC
β¨ Purpose
STREVC computes some or all of the right and/or left eigenvectors of a real upper quasi-triangular matrix T. Matrices of this type are produced by the Schur factorization of a real general matrix: A = Q*T*Q**T, as computed by SHSEQR. Same deal as before, just REAL instead of DOUBLE PRECISION β the β¨budgetβ¨ version, but make no mistake, she's still main character πΈ
The right eigenvector x and the left eigenvector y of T corresponding to an eigenvalue w are defined by:
T*x = w*x, (y**H)*T = w*(y**H)
where y**H denotes the conjugate transpose of y. The eigenvalues are not input to this routine β they're read directly from the diagonal blocks of T. No, you don't hand her the eigenvalues. She reads them off the diagonal herself, iykyk π
This routine returns the matrices X and/or Y of right and left eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an input matrix. If Q is the orthogonal factor that reduces a matrix A to Schur form T, then Q*X and Q*Y are the matrices of right and left eigenvectors of A. The way that one routine can just hand you eigenvectors of A without ever seeing Aβ¦ obsessed π«Ά
π Parameters
SIDEβCHARACTER*1. Which side are we doing, bestie?= 'R': compute right eigenvectors only;= 'L': compute left eigenvectors only;= 'B': compute both right and left eigenvectors.
HOWMNYβCHARACTER*1. How many, and do we backtransform?= 'A': compute all right and/or left eigenvectors;= 'B': compute all right and/or left eigenvectors, backtransformed by the matrices inVRand/orVL;= 'S': compute selected right and/or left eigenvectors, as indicated by the logical arraySELECT.
SELECTβLOGICALarray, dimension(N). IfHOWMNY = 'S',SELECTspecifies the eigenvectors to be computed. Ifw(j)is a real eigenvalue, the corresponding real eigenvector is computed ifSELECT(j)is.TRUE.. Ifw(j)andw(j+1)are the real and imaginary parts of a complex eigenvalue, the corresponding complex eigenvector is computed if eitherSELECT(j)orSELECT(j+1)is.TRUE., and on exitSELECT(j)is set to.TRUE.andSELECT(j+1)is set to.FALSE.. Not referenced ifHOWMNY = 'A'or'B'. So if you flag either half of a complex pair, she takes the pair β and then quietly tidies up your flags for you. Mother behavior πNβINTEGER. The order of the matrix T.N >= 0.TβREALarray, dimension(LDT,N). The upper quasi-triangular matrix T in Schur canonical form. Quasi-triangular = the diagonal may have lil 2-by-2 blocks chilling in it for complex eigenvalue pairs. That's just how she rolls β¨LDTβINTEGER. The leading dimension of the array T.LDT >= max(1,N). Note themax(1,N)β she's being polite about theN = 0case π«ΆVLβREALarray, dimension(LDVL,MM). On entry, ifSIDE = 'L'or'B'andHOWMNY = 'B',VLmust contain an N-by-N matrix Q (usually the orthogonal matrix Q of Schur vectors returned bySHSEQR). On exit, ifSIDE = 'L'or'B',VLcontains:- if
HOWMNY = 'A', the matrix Y of left eigenvectors of T; - if
HOWMNY = 'B', the matrix Q*Y; - if
HOWMNY = 'S', the left eigenvectors of T specified bySELECT, stored consecutively in the columns ofVL, in the same order as their eigenvalues.
- if
A complex eigenvector corresponding to a complex eigenvalue is stored in two consecutive columns, the first holding the real part, and the second the imaginary part. Not referenced if SIDE = 'R'.
LDVLβINTEGER. The leading dimension of the arrayVL.LDVL >= 1, and ifSIDE = 'L'or'B', thenLDVL >= N.VRβREALarray, dimension(LDVR,MM). On entry, ifSIDE = 'R'or'B'andHOWMNY = 'B',VRmust contain an N-by-N matrix Q (usually the orthogonal matrix Q of Schur vectors returned bySHSEQR). On exit, ifSIDE = 'R'or'B',VRcontains:- if
HOWMNY = 'A', the matrix X of right eigenvectors of T; - if
HOWMNY = 'B', the matrix Q*X; - if
HOWMNY = 'S', the right eigenvectors of T specified bySELECT, stored consecutively in the columns ofVR, in the same order as their eigenvalues.
- if
A complex eigenvector corresponding to a complex eigenvalue is stored in two consecutive columns, the first holding the real part and the second the imaginary part. Not referenced if SIDE = 'L'.
LDVRβINTEGER. The leading dimension of the arrayVR.LDVR >= 1, and ifSIDE = 'R'or'B', thenLDVR >= N.MMβINTEGER. The number of columns in the arraysVLand/orVR.MM >= M.MβINTEGER. The number of columns in the arraysVLand/orVRactually used to store the eigenvectors. IfHOWMNY = 'A'or'B',Mis set toN. Each selected real eigenvector occupies one column and each selected complex eigenvector occupies two columns.WORKβREALarray, dimension(3*N). Three times N of scratch space, same deal, hands off πINFOβINTEGER. The verdict:= 0: successful exit π< 0: ifINFO = -i, thei-th argument had an illegal value argument-INFOsaid something out of pocket, go apologize to it π
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.
Further Details:
The algorithm used in this program is basically backward (forward) substitution, with scaling to make the the code robust against possible overflow. (That double "the the" again β she's a family trait at this point. Preserved word for word, no cap π)
Each eigenvector is normalized so that the element of largest magnitude has magnitude 1; here the magnitude of a complex number (x,y) is taken to be |x| + |y|. Max element gets magnitude 1, complex magnitude is |x| + |y|. Same normalization energy as her double-precision sister, and tbh it ate π₯
Definition at line 220 of file strevc.f.
okay so here's the exact signature for ztrevc, bestie β don't touch a character:
subroutine ztrevc (character side, character howmny, logical, dimension( * )
select, integer n, complex*16, dimension( ldt, * ) t, integer ldt,
complex*16, dimension( ldvl, * ) vl, integer ldvl, complex*16,
dimension( ldvr, * ) vr, integer ldvr, integer mm, integer m,
complex*16, dimension( * ) work, double precision, dimension( * ) rwork,
integer info)
π« ZTREVC π«
Purpose:
ZTREVC computes some or all of the right and/or left eigenvectors of a complex upper triangular matrix T. Matrices of this type are produced by the Schur factorization of a complex general matrix: A = Q*T*Q**H, as computed by ZHSEQR.
The right eigenvector x and the left eigenvector y of T corresponding to an eigenvalue w are defined by:
T*x = w*x, (y**H)*T = w*(y**H)
where y**H denotes the conjugate transpose of the vector y. The eigenvalues are not input to this routine, but are read directly from the diagonal of T.
This routine returns the matrices X and/or Y of right and left eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an input matrix. If Q is the unitary factor that reduces a matrix A to Schur form T, then Q*X and Q*Y are the matrices of right and left eigenvectors of A. iconic behavior, honestly. β¨
πΈ Parameters
SIDEβCHARACTER*1. Tells us which side's eigenvectors we're grabbing:'R': compute right eigenvectors only;'L': compute left eigenvectors only;'B': compute both right and left eigenvectors.
HOWMNYβCHARACTER*1. Controls how many and which eigenvectors:'A': compute all right and/or left eigenvectors;'B': compute all right and/or left eigenvectors, backtransformed using the matrices supplied inVRand/orVL;'S': compute selected right and/or left eigenvectors, as indicated by the logical arraySELECT.
SELECTβLOGICAL array, dimension (N). IfHOWMNY = 'S',SELECTspecifies the eigenvectors to be computed. The eigenvector corresponding to the j-th eigenvalue is computed ifSELECT(j) = .TRUE.. Not referenced ifHOWMNY = 'A'or'B'.NβINTEGER. The order of the matrixT.N >= 0.TβCOMPLEX*16 array, dimension (LDT,N). The upper triangular matrixT.Tis modified, but restored on exit. no cap, it puts itself back.LDTβINTEGER. The leading dimension of the arrayT.LDT >= max(1,N).VLβCOMPLEX*16 array, dimension (LDVL,MM). On entry, ifSIDE = 'L'or'B'andHOWMNY = 'B',VLmust contain an N-by-N matrixQ(usually the unitary matrixQof Schur vectors returned byZHSEQR). On exit, ifSIDE = 'L'or'B',VLcontains:- if
HOWMNY = 'A', the matrixYof left eigenvectors ofT; - if
HOWMNY = 'B', the matrixQ*Y; - if
HOWMNY = 'S', the left eigenvectors ofTspecified bySELECT, stored consecutively in the columns ofVL, in the same order as their eigenvalues.
- if
Not referenced if SIDE = 'R'.
LDVLβINTEGER. The leading dimension of the arrayVL.LDVL >= 1, and ifSIDE = 'L'or'B',LDVL >= N.VRβCOMPLEX*16 array, dimension (LDVR,MM). On entry, ifSIDE = 'R'or'B'andHOWMNY = 'B',VRmust contain an N-by-N matrixQ(usually the unitary matrixQof Schur vectors returned byZHSEQR). On exit, ifSIDE = 'R'or'B',VRcontains:- if
HOWMNY = 'A', the matrixXof right eigenvectors ofT; - if
HOWMNY = 'B', the matrixQ*X; - if
HOWMNY = 'S', the right eigenvectors ofTspecified bySELECT, stored consecutively in the columns ofVR, in the same order as their eigenvalues.
- if
Not referenced if SIDE = 'L'.
LDVRβINTEGER. The leading dimension of the arrayVR.LDVR >= 1, and ifSIDE = 'R'or'B';LDVR >= N.MMβINTEGER. The number of columns in the arraysVLand/orVR.MM >= M.MβINTEGER. The number of columns in the arraysVLand/orVRactually used to store the eigenvectors. IfHOWMNY = 'A'or'B',Mis set toN. Each selected eigenvector occupies one column.WORKβCOMPLEX*16 array, dimension (2*N).RWORKβDOUBLE PRECISION array, dimension (N).INFOβINTEGER. The vibe check:= 0: successful exit< 0: ifINFO = -i, the i-th argument had an illegal value
π Author
- Univ. of Tennessee
- Univ. of California Berkeley
- Univ. of Colorado Denver
- NAG Ltd.
π Further Details
The algorithm used in this program is basically backward (forward) substitution, with scaling to make the the code robust against possible overflow. yes, βthe theβ is literally in the source β leaving it exactly as found, bestie. π
Each eigenvector is normalized so that the element of largest magnitude has magnitude 1; here the magnitude of a complex number (x,y) is taken to be |x| + |y|.
Definition at line 216 of file ztrevc.f.
π€ Author
Generated automatically by Doxygen for LAPACK from the source code.
and that's the whole page, bestie π the footer at the very bottom says LAPACK Version 3.12.0 and trevc(3) β no date shown, just the version and the page name. periodt. β¨π«Ά
π¦ where this page comes from
- arch rolling: lapack-doc 3.12.1-2 Β· custom
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms