Changeset 31c6e9 in git


Ignore:
Timestamp:
Mar 3, 2021, 4:56:47 PM (3 years ago)
Author:
Hans Schoenemann <hannes@…>
Branches:
(u'spielwiese', '17f1d200f27c5bd38f5dfc6e8a0879242279d1d8')
Children:
8bf51f59b9dcce7af6334bc9dc6ad15a2a523002
Parents:
471da6a284cf3893ba07cde8e9d3036f088a01384d8049f1ac15e575ca3192329049bfdba1bfcfe2
Message:
Merge branch 'spielwiese' of github.com:Singular/Singular into spielwiese
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • .github/workflows/runtests.yml

    r471da6a r31c6e9  
    1313      matrix:
    1414        os: [ubuntu-latest, macos-latest]
    15         configflags: ["", "--without-ntl --with-flint"]
     15        configflags: ["", "--with-ntl --with-flint", "--without-ntl --with-flint"]
    1616
    1717    steps:
     
    1919      - name: "Install dependencies"
    2020        run: |
     21               FLINT_JLL="https://github.com/JuliaBinaryWrappers/FLINT_jll.jl/releases/download/FLINT-v200.700.0%2B0/FLINT.v200.700.0"
    2122               if [ "$RUNNER_OS" == "Linux" ]; then
    2223                    # sharutils is for uudecode
    2324                    sudo apt install sharutils libgmp-dev libreadline-dev libmpfr-dev libntl-dev libcdd-dev 4ti2 normaliz
    24                     # install new enough FLINT (>= 2.6.0)
    25                     wget -O FLINT.tar.gz "https://github.com/JuliaBinaryWrappers/FLINT_jll.jl/releases/download/FLINT-v2.6.0%2B0/FLINT.v2.6.0.x86_64-linux-gnu.tar.gz"
     25                    # install new enough FLINT
     26                    wget -O FLINT.tar.gz "${FLINT_JLL}.x86_64-linux-gnu.tar.gz"
    2627                    sudo tar -C /usr -xvf FLINT.tar.gz
    2728                    rm -f FLINT.tar.gz
    2829               elif [ "$RUNNER_OS" == "macOS" ]; then
    29                     brew install autoconf automake libtool gmp readline mpfr ntl flint cddlib
     30                    brew install autoconf automake libtool gmp readline mpfr ntl cddlib
    3031                    # TODO: 4ti2?
    3132                    # TODO: normaliz?
     33                    # install new enough FLINT
     34                    wget -O FLINT.tar.gz "${FLINT_JLL}.x86_64-apple-darwin.tar.gz"
     35                    sudo mkdir -p /usr/local
     36                    sudo tar -C /usr/local -xvf FLINT.tar.gz
     37                    rm -f FLINT.tar.gz
    3238               else
    3339                    echo "$RUNNER_OS not supported"
     
    3945      - run: make check
    4046      - run: make install
     47      - run: cd Tst && ./regress.cmd -s $prefix/bin/Singular Old/universal.lst
     48        if: ${{ always() }}
     49      #- run: cd Tst && ./regress.cmd -s $prefix/bin/Singular Buch/buch.lst
     50      #  if: ${{ always() }}
     51      - run: cd Tst && ./regress.cmd -s $prefix/bin/Singular Plural/short.lst
     52        if: ${{ always() }}
     53      - run: cd Tst && ./regress.cmd -s $prefix/bin/Singular Plural/dmod.lst
     54        if: ${{ always() }}
     55      - run: cd Tst && ./regress.cmd -s $prefix/bin/Singular Short/ok_s.lst
     56        if: ${{ always() }}
     57      #- run: cd Tst && ./regress.cmd -s $prefix/bin/Singular Long/ok_l.lst
     58      #  if: ${{ always() }}
    4159
    4260# TODO: code coverage?
  • Singular/iparith.cc

    r4d8049f r31c6e9  
    68106810     }
    68116811  }
    6812   idhdl h=(idhdl)w->data;
    6813   res->data = (char *)idModulo(u_id,v_id ,hom,&w_u, &(h->data.umatrix),alg);
     6812  res->data = (char *)idModulo(u_id,v_id ,hom,&w_u, NULL,alg);
    68146813  if (w_u!=NULL)
    68156814  {
     
    68556854  return FALSE;
    68566855}
    6857 static BOOLEAN jjLIFTSTD3(leftv res, leftv u, leftv v, leftv w)
     6856static BOOLEAN jjLIFTSTD_SYZ(leftv res, leftv u, leftv v, leftv w)
    68586857{
    68596858  if ((v->rtyp!=IDHDL)||(v->e!=NULL)) return TRUE;
     
    68766875                                &(hw->data.uideal));
    68776876  setFlag(res,FLAG_STD); v->flag=0; w->flag=0;
     6877  return FALSE;
     6878}
     6879static BOOLEAN jjLIFTSTD_ALG(leftv res, leftv u, leftv v, leftv w)
     6880{
     6881  if ((v->rtyp!=IDHDL)||(v->e!=NULL)) return TRUE;
     6882  idhdl hv=(idhdl)v->data;
     6883  GbVariant alg=syGetAlgorithm((char*)w->Data(),currRing,(ideal)u->Data());
     6884#ifdef HAVE_SHIFTBBA
     6885  if (rIsLPRing(currRing))
     6886  {
     6887    if (currRing->LPncGenCount < IDELEMS((ideal)u->Data()))
     6888    {
     6889      Werror("At least %d ncgen variables are needed for this computation.", IDELEMS((ideal)u->Data()));
     6890      return TRUE;
     6891    }
     6892  }
     6893#endif
     6894  // CopyD for IDEAL_CMD and MODUL_CMD are identical:
     6895  res->data = (char *)idLiftStd((ideal)u->Data(),
     6896                                &(hv->data.umatrix),testHomog,
     6897                                NULL,alg);
     6898  setFlag(res,FLAG_STD); v->flag=0;
     6899  return FALSE;
     6900}
     6901static BOOLEAN jjLIFTSTD_LIMIT(leftv res, leftv u, leftv v, leftv w)
     6902{
     6903  if ((v->rtyp!=IDHDL)||(v->e!=NULL)) return TRUE;
     6904  idhdl hv=(idhdl)v->data;
     6905#ifdef HAVE_SHIFTBBA
     6906  if (rIsLPRing(currRing))
     6907  {
     6908    if (currRing->LPncGenCount < IDELEMS((ideal)u->Data()))
     6909    {
     6910      Werror("At least %d ncgen variables are needed for this computation.", IDELEMS((ideal)u->Data()));
     6911      return TRUE;
     6912    }
     6913  }
     6914#endif
     6915  // CopyD for IDEAL_CMD and MODUL_CMD are identical:
     6916  res->data = (char *)idLiftStd((ideal)u->Data(),
     6917                                &(hv->data.umatrix),testHomog,
     6918                                NULL,GbDefault,(ideal)w->Data());
     6919  setFlag(res,FLAG_STD); v->flag=0;
    68786920  return FALSE;
    68796921}
     
    77827824  }
    77837825}
    7784 static BOOLEAN jjLIFTSTD_4(leftv res, leftv U)
    7785 {
    7786   const short t1[]={4,IDEAL_CMD,MATRIX_CMD,MODUL_CMD,STRING_CMD};
    7787   const short t2[]={4,MODUL_CMD,MATRIX_CMD,MODUL_CMD,STRING_CMD};
     7826static BOOLEAN jjLIFTSTD_M(leftv res, leftv U)
     7827{
     7828  // we have 4 or 5 arguments
    77887829  leftv u=U;
    77897830  leftv v=u->next;
    7790   leftv w=v->next;
    7791   leftv u4=w->next;
    7792   if (v->rtyp!=IDHDL) return TRUE;
    7793   if (w->rtyp!=IDHDL) return TRUE;
    7794   if (iiCheckTypes(U,t1)||iiCheckTypes(U,t2))
    7795   {
    7796     // see jjLIFTSTD3
    7797     ideal I=(ideal)u->Data();
    7798     idhdl hv=(idhdl)v->data;
    7799     idhdl hw=(idhdl)w->data;
    7800     GbVariant alg=syGetAlgorithm((char*)u4->Data(),currRing,I);
    7801     // CopyD for IDEAL_CMD and MODUL_CMD are identical:
    7802     res->rtyp = u->Typ();
    7803     res->data = (char *)idLiftStd((ideal)u->Data(),
    7804                                 &(hv->data.umatrix),testHomog,
    7805                                 &(hw->data.uideal),alg);
    7806     setFlag(res,FLAG_STD); v->flag=0; w->flag=0;
    7807     return FALSE;
     7831  leftv u3=v->next;
     7832  leftv u4=u3->next;
     7833  leftv u5=u4->next; // might be NULL
     7834
     7835  ideal *syz=NULL;
     7836  GbVariant alg=GbDefault;
     7837  ideal h11=NULL;
     7838
     7839  if(u5==NULL)
     7840  {
     7841    // test all three possibilities for 4 arguments
     7842    const short t1[]={4,IDEAL_CMD,MATRIX_CMD,MODUL_CMD,STRING_CMD};
     7843    const short t2[]={4,MODUL_CMD,MATRIX_CMD,MODUL_CMD,STRING_CMD};
     7844    const short t3[]={4,IDEAL_CMD,MATRIX_CMD,MODUL_CMD,IDEAL_CMD};
     7845    const short t4[]={4,MODUL_CMD,MATRIX_CMD,MODUL_CMD,MODUL_CMD};
     7846    const short t5[]={4,IDEAL_CMD,MATRIX_CMD,STRING_CMD,IDEAL_CMD};
     7847    const short t6[]={4,MODUL_CMD,MATRIX_CMD,STRING_CMD,MODUL_CMD};
     7848
     7849    if(iiCheckTypes(U,t1)||iiCheckTypes(U,t2))
     7850    {
     7851      if ((u3->rtyp!=IDHDL)||(u3->e!=NULL)) return TRUE;
     7852      idhdl hw=(idhdl)u3->data;
     7853      syz=&(hw->data.uideal);
     7854      alg=syGetAlgorithm((char*)u4->Data(),currRing,(ideal)u->Data());
     7855    }
     7856    else if(iiCheckTypes(U,t3)||iiCheckTypes(U,t4))
     7857    {
     7858      if ((u3->rtyp!=IDHDL)||(u3->e!=NULL)) return TRUE;
     7859      idhdl hw=(idhdl)u3->data;
     7860      syz=&(hw->data.uideal);
     7861      h11=(ideal)u4->Data();
     7862    }
     7863    else if(iiCheckTypes(U,t5)||iiCheckTypes(U,t6))
     7864    {
     7865      alg=syGetAlgorithm((char*)u3->Data(),currRing,(ideal)u->Data());
     7866      h11=(ideal)u4->Data();
     7867    }
     7868    else
     7869    {
     7870      Werror("%s(`ideal/module`,`matrix`[,`module`][,`string`][,`ideal/module`]) expected",Tok2Cmdname(iiOp));
     7871      return TRUE;
     7872    }
    78087873  }
    78097874  else
    78107875  {
    7811     Werror("%s(`ideal`,`matrix`,`module`,`string`)\n"
    7812            "or (`module`,`matrix`,`module`,`string`) expected",
    7813            Tok2Cmdname(iiOp));
    7814     return TRUE;
    7815   }
     7876    // we have 5 arguments
     7877    const short t1[]={5,IDEAL_CMD,MATRIX_CMD,MODUL_CMD,STRING_CMD,IDEAL_CMD};
     7878    const short t2[]={5,MODUL_CMD,MATRIX_CMD,MODUL_CMD,STRING_CMD,MODUL_CMD};
     7879    if(iiCheckTypes(U,t1)||iiCheckTypes(U,t2))
     7880    {
     7881      idhdl hw=(idhdl)u3->data;
     7882      syz=&(hw->data.uideal);
     7883      alg=syGetAlgorithm((char*)u4->Data(),currRing,(ideal)u->Data());
     7884    }
     7885    else
     7886    {
     7887      Werror("%s(`ideal/module`,`matrix`[,`module`][,`string`][,`ideal/module`]) expected",Tok2Cmdname(iiOp));
     7888      return TRUE;
     7889    }
     7890  }
     7891
     7892#ifdef HAVE_SHIFTBBA
     7893  if (rIsLPRing(currRing))
     7894  {
     7895    if (currRing->LPncGenCount < IDELEMS((ideal)u->Data()))
     7896    {
     7897      Werror("At least %d ncgen variables are needed for this computation.", IDELEMS((ideal)u->Data()));
     7898      return TRUE;
     7899    }
     7900  }
     7901#endif
     7902
     7903  if ((v->rtyp!=IDHDL)||(v->e!=NULL)) return TRUE;
     7904  idhdl hv=(idhdl)v->data;
     7905  // CopyD for IDEAL_CMD and MODUL_CMD are identical:
     7906  res->rtyp = u->Typ();
     7907  res->data = (char *)idLiftStd((ideal)u->Data(),
     7908                              &(hv->data.umatrix),testHomog,
     7909                              syz,alg,h11);
     7910  setFlag(res,FLAG_STD); v->flag=0;
     7911  if(syz!=NULL)
     7912    u3->flag=0;
     7913  return FALSE;
    78167914}
    78177915BOOLEAN jjLIST_PL(leftv res, leftv v)
     
    78647962  }
    78657963  res->data=(char *)L;
     7964  return FALSE;
     7965}
     7966static BOOLEAN jjMODULO4(leftv res, leftv u)
     7967{
     7968  leftv v=u->next;
     7969  leftv w=v->next;
     7970  leftv u4=w->next;
     7971  GbVariant alg;
     7972  ideal u_id,v_id;
     7973  // we have 4 arguments
     7974  const short t1[]={4,IDEAL_CMD,IDEAL_CMD,MATRIX_CMD,STRING_CMD};
     7975  const short t2[]={4,MODUL_CMD,MODUL_CMD,MATRIX_CMD,STRING_CMD};
     7976  if(iiCheckTypes(u,t1)||iiCheckTypes(u,t2)||(w->rtyp!=IDHDL))
     7977  {
     7978    u_id=(ideal)u->Data();
     7979    v_id=(ideal)v->Data();
     7980    alg=syGetAlgorithm((char*)u4->Data(),currRing,u_id);
     7981  }
     7982  else
     7983  {
     7984    Werror("%s(`ideal/module`,`ideal/module`[,`matrix`][,`string`]) expected",Tok2Cmdname(iiOp));
     7985    return TRUE;
     7986  }
     7987  intvec *w_u=(intvec *)atGet(u,"isHomog",INTVEC_CMD);
     7988  tHomog hom=testHomog;
     7989  if (w_u!=NULL)
     7990  {
     7991    w_u=ivCopy(w_u);
     7992    hom=isHomog;
     7993  }
     7994  intvec *w_v=(intvec *)atGet(v,"isHomog",INTVEC_CMD);
     7995  if (w_v!=NULL)
     7996  {
     7997    w_v=ivCopy(w_v);
     7998    hom=isHomog;
     7999  }
     8000  if ((w_u!=NULL) && (w_v==NULL))
     8001    w_v=ivCopy(w_u);
     8002  if ((w_v!=NULL) && (w_u==NULL))
     8003    w_u=ivCopy(w_v);
     8004  if (w_u!=NULL)
     8005  {
     8006     if ((*w_u).compare((w_v))!=0)
     8007     {
     8008       WarnS("incompatible weights");
     8009       delete w_u; w_u=NULL;
     8010       hom=testHomog;
     8011     }
     8012     else
     8013     {
     8014       if ((!idTestHomModule(u_id,currRing->qideal,w_v))
     8015       || (!idTestHomModule(v_id,currRing->qideal,w_v)))
     8016       {
     8017         WarnS("wrong weights");
     8018         delete w_u; w_u=NULL;
     8019         hom=testHomog;
     8020       }
     8021     }
     8022  }
     8023  idhdl h=(idhdl)w->data;
     8024  res->data = (char *)idModulo(u_id,v_id ,hom,&w_u, &(h->data.umatrix),alg);
     8025  if (w_u!=NULL)
     8026  {
     8027    atSet(res,omStrDup("isHomog"),w_u,INTVEC_CMD);
     8028  }
     8029  delete w_v;
     8030  //if (TEST_OPT_RETURN_SB) setFlag(res,FLAG_STD);
    78668031  return FALSE;
    78678032}
  • Singular/iparith.inc

    r4d8049f r31c6e9  
    684684// operation: liftstd (ideal, matrix, module)  ->  ideal
    685685// operation: liftstd (module, matrix, module)  ->  module
     686// operation: liftstd (ideal, matrix, string)  ->  ideal
     687// operation: liftstd (module, matrix, string)  ->  module
     688// operation: liftstd (ideal, matrix, ideal)  ->  ideal
     689// operation: liftstd (module, matrix, module)  ->  module
    686690// operation: matrix (ideal, int, int)  ->  matrix
    687691// operation: matrix (module, int, int)  ->  matrix
     
    755759// operation: liftstd (...)  ->  ideal ( 3 arguments )
    756760// operation: liftstd (...)  ->  ideal ( 4 arguments )
     761// operation: liftstd (...)  ->  ideal ( 5 arguments )
    757762// operation: list (...)  ->  list ( any number of arguments )
    758763// operation: luinverse (...)  ->  list ( number of arguments >0 )
  • Singular/table.h

    r4d8049f r31c6e9  
    845845,{D(jjLIFT3),          LIFT_CMD,   MATRIX_CMD, IDEAL_CMD,  IDEAL_CMD,  MATRIX_CMD, ALLOW_NC |ALLOW_RING}
    846846,{D(jjLIFT3),          LIFT_CMD,   MATRIX_CMD, MODUL_CMD,  MODUL_CMD,  MATRIX_CMD, ALLOW_NC |ALLOW_RING}
    847 ,{D(jjLIFTSTD3),       LIFTSTD_CMD,IDEAL_CMD,  IDEAL_CMD,  MATRIX_CMD, MODUL_CMD, ALLOW_NC |ALLOW_RING}
    848 ,{D(jjLIFTSTD3),       LIFTSTD_CMD,MODUL_CMD,  MODUL_CMD,  MATRIX_CMD, MODUL_CMD, ALLOW_NC |ALLOW_RING}
     847,{D(jjLIFTSTD_SYZ),    LIFTSTD_CMD,IDEAL_CMD,  IDEAL_CMD,  MATRIX_CMD, MODUL_CMD, ALLOW_NC |ALLOW_RING}
     848,{D(jjLIFTSTD_SYZ),    LIFTSTD_CMD,MODUL_CMD,  MODUL_CMD,  MATRIX_CMD, MODUL_CMD, ALLOW_NC |ALLOW_RING}
     849,{D(jjLIFTSTD_ALG),    LIFTSTD_CMD,IDEAL_CMD,  IDEAL_CMD,  MATRIX_CMD, STRING_CMD, ALLOW_NC |ALLOW_RING}
     850,{D(jjLIFTSTD_ALG),    LIFTSTD_CMD,MODUL_CMD,  MODUL_CMD,  MATRIX_CMD, STRING_CMD, ALLOW_NC |ALLOW_RING}
     851,{D(jjLIFTSTD_LIMIT),  LIFTSTD_CMD,IDEAL_CMD,  IDEAL_CMD,  MATRIX_CMD, IDEAL_CMD, ALLOW_NC |ALLOW_RING}
     852,{D(jjLIFTSTD_LIMIT),  LIFTSTD_CMD,MODUL_CMD,  MODUL_CMD,  MATRIX_CMD, MODUL_CMD, ALLOW_NC |ALLOW_RING}
    849853,{D(jjMATRIX_Id),      MATRIX_CMD, MATRIX_CMD, IDEAL_CMD,  INT_CMD,    INT_CMD, ALLOW_NC |ALLOW_RING}
    850854,{D(jjMATRIX_Mo),      MATRIX_CMD, MATRIX_CMD, MODUL_CMD,  INT_CMD,    INT_CMD, ALLOW_NC |ALLOW_RING}
     
    944948,{D(jjCALL2ARG),  LIFTSTD_CMD,     IDEAL_CMD,/*or MODUL*/2  , ALLOW_NC |ALLOW_RING}
    945949,{D(jjCALL3ARG),  LIFTSTD_CMD,     IDEAL_CMD,/*or MODUL*/3  , ALLOW_NC |ALLOW_RING}
    946 ,{D(jjLIFTSTD_4), LIFTSTD_CMD,     IDEAL_CMD,/*or MODUL*/4  , ALLOW_PLURAL |ALLOW_RING}
     950,{D(jjLIFTSTD_M), LIFTSTD_CMD,     IDEAL_CMD,/*or MODUL*/4  , ALLOW_NC |ALLOW_RING}
     951,{D(jjLIFTSTD_M), LIFTSTD_CMD,     IDEAL_CMD,/*or MODUL*/5  , ALLOW_NC |ALLOW_RING}
    947952,{D(jjLIST_PL),   LIST_CMD,        LIST_CMD,           -1      , ALLOW_NC |ALLOW_RING}
    948953,{D(jjLU_INVERSE),LUI_CMD,         LIST_CMD,           -2      , NO_NC |NO_RING}
     
    954959,{D(jjCALL2ARG),  MODULO_CMD,      MODUL_CMD,           2      , ALLOW_NC |ALLOW_RING}
    955960,{D(jjCALL3ARG),  MODULO_CMD,      MODUL_CMD,           3      , ALLOW_NC |ALLOW_RING}
     961,{D(jjMODULO4),   MODULO_CMD,      MODUL_CMD,           4      , ALLOW_NC |ALLOW_RING}
    956962,{D(jjCALL1ARG),  NAMES_CMD,       LIST_CMD,            1      , ALLOW_NC |ALLOW_RING}
    957963,{D(jjNAMES0),    NAMES_CMD,       LIST_CMD,            0      , ALLOW_NC |ALLOW_RING}
  • Tst/Short/ok_s.lst

    r4d8049f r31c6e9  
    123123homalg
    124124invar_lib
     125liftstd_m
    125126modular_s
    126127modstd_s
  • kernel/ideals.cc

    r4d8049f r31c6e9  
    857857* in ma
    858858*/
    859 ideal idLiftStd (ideal  h1, matrix* ma, tHomog hi, ideal * syz, GbVariant alg)
     859ideal idLiftStd (ideal  h1, matrix* ma, tHomog hi, ideal * syz, GbVariant alg,
     860  ideal h11)
    860861{
    861862  int  i, j, t, inputIsIdeal=id_RankFreeModule(h1,currRing);
     
    895896  else
    896897    s_h1 = h1;
    897 
    898   ideal s_h3=idPrepare(s_h1,NULL,hi,k,&w,alg); // main (syz) GB computation
     898  ideal s_h11=NULL;
     899  if (h11!=NULL)
     900  {
     901    s_h11=idrCopyR_NoSort(h11,orig_ring,syz_ring);
     902  }
     903
     904
     905  ideal s_h3=idPrepare(s_h1,s_h11,hi,k,&w,alg); // main (syz) GB computation
    899906
    900907  ideal s_h2 = idInit(IDELEMS(s_h3), s_h3->rank);
     
    921928          if (pGetComp(pNext(q)) > k)
    922929          {
    923             s_h2->m[j] = pNext(q);
     930            s_h2->m[i-1] = pNext(q);
    924931            pNext(q) = NULL;
    925932          }
     
    962969  {
    963970    idDelete(&s_h1);
     971    if (s_h11!=NULL) idDelete(&s_h11);
    964972    rChangeCurrRing(orig_ring);
    965973  }
     
    967975  *ma = mpNew(j,i);
    968976
    969   i = 1;
    970   for (j=0; j<IDELEMS(s_h2); j++)
     977  for (j=0; j<i; j++)
    971978  {
    972979    if (s_h2->m[j] != NULL)
     
    986993          pSetComp(p,0);
    987994          pSetmComp(p);
    988           MATELEM(*ma,t-k,i) = pAdd(MATELEM(*ma,t-k,i),p);
     995          MATELEM(*ma,t-k,j+1) = pAdd(MATELEM(*ma,t-k,j+1),p);
    989996        }
    990997      }
    991       i++;
    992998    }
    993999  }
  • kernel/ideals.h

    r4d8049f r31c6e9  
    138138ideal   idSyzygies (ideal h1, tHomog h,intvec **w, BOOLEAN setSyzComp=TRUE,
    139139                    BOOLEAN setRegularity=FALSE, int *deg = NULL, GbVariant a=GbDefault);
    140 ideal   idLiftStd  (ideal h1, matrix *m, tHomog h=testHomog, ideal *syz=NULL, GbVariant a=GbDefault);
     140ideal   idLiftStd  (ideal h1, matrix *m, tHomog h=testHomog, ideal *syz=NULL, GbVariant a=GbDefault, ideal h11=NULL);
    141141
    142142ideal   idLift (ideal mod, ideal submod,ideal * rest=NULL,
Note: See TracChangeset for help on using the changeset viewer.