*** /home/rubey/tmp/combfunc.spad.pamphlet~	2005-10-03 16:06:19.000000000 +0200
--- combfunc.spad.pamphlet	2005-10-04 14:11:13.000000000 +0200
***************
*** 130,136 ****
--- 130,138 ----
      idsum     : List F -> F
      iprod     : List F -> F
      idprod    : List F -> F
+     dsum      : List F -> O
      ddsum     : List F -> O
+     dprod     : List F -> O
      ddprod    : List F -> O
      fourth    : List F -> F
      dvpow1    : List F -> F
***************
*** 138,150 ****
      summand   : List F -> F
      dvsum     : (List F, SE) -> F
      dvdsum    : (List F, SE) -> F
      facts     : (F, List SE) -> F
      K2fact    : (K, List SE) -> F
      smpfact   : (SMP, List SE) -> F
  
      dummy == new()$SE :: F
  @
- 
  This macro will be used in [[product]] and [[summation]], both the $5$ and $3$
  argument forms. It is used to introduce a dummy variable in place of the
  summation index within the summands. This in turn is necessary to keep the
--- 140,153 ----
      summand   : List F -> F
      dvsum     : (List F, SE) -> F
      dvdsum    : (List F, SE) -> F
+     dvprod    : (List F, SE) -> F
+     dvdprod   : (List F, SE) -> F
      facts     : (F, List SE) -> F
      K2fact    : (K, List SE) -> F
      smpfact   : (SMP, List SE) -> F
  
      dummy == new()$SE :: F
  @
  This macro will be used in [[product]] and [[summation]], both the $5$ and $3$
  argument forms. It is used to introduce a dummy variable in place of the
  summation index within the summands. This in turn is necessary to keep the
***************
*** 155,167 ****
  product.
  
  Note that up to [[patch--25]] this used to read
- 
  \begin{verbatim}
      dummy := new()$SE :: F
  \end{verbatim}
- 
  thus introducing the same dummy variable for all products and summations, which
! caused nested products and summations fail. (Issue~\#72)
  
  <<package COMBF CombinatorialFunction>>=
      opfact  := operator("factorial"::Symbol)$CommonOperators
--- 158,168 ----
  product.
  
  Note that up to [[patch--25]] this used to read
  \begin{verbatim}
      dummy := new()$SE :: F
  \end{verbatim}
  thus introducing the same dummy variable for all products and summations, which
! caused nested products and summations to fail. (Issue~\#72)
  
  <<package COMBF CombinatorialFunction>>=
      opfact  := operator("factorial"::Symbol)$CommonOperators
***************
*** 219,233 ****
        opsum [eval(x, k := kernel(i)$K, dm), dm, k::F]
  
  @
- 
  These two operations return the product or the sum as unevaluated operators. A
  dummy variable is introduced to make the indexing variable \lq local\rq.
  
  <<package COMBF CombinatorialFunction>>=
      dvsum(l, x) ==
!       k  := retract(second l)@K
!       differentiate(third l, x) * summand l
!           + opsum [differentiate(first l, x), second l, third l]
  
      dvdsum(l, x) ==
        x = retract(y := third l)@SE => 0
--- 220,231 ----
        opsum [eval(x, k := kernel(i)$K, dm), dm, k::F]
  
  @
  These two operations return the product or the sum as unevaluated operators. A
  dummy variable is introduced to make the indexing variable \lq local\rq.
  
  <<package COMBF CombinatorialFunction>>=
      dvsum(l, x) ==
!       opsum [differentiate(first l, x), second l, third l]
  
      dvdsum(l, x) ==
        x = retract(y := third l)@SE => 0
***************
*** 238,249 ****
          opdsum [differentiate(first l, x), second l, y, g, h]
  
  @
! 
! The above operation implements differentiation of sums with bounds. Note that
! the function
! 
  $$n\mapsto\sum_{k=1}^n f(k,n)$$
- 
  is well defined only for integral values of $n$ greater than or equal to zero.
  There is not even consensus how to define this function for $n<0$. Thus, it is
  not differentiable. Therefore, we need to check whether we erroneously are
--- 236,244 ----
          opdsum [differentiate(first l, x), second l, y, g, h]
  
  @
! The above two operations implement differentiation of sums with and without
! bounds. Note that the function
  $$n\mapsto\sum_{k=1}^n f(k,n)$$
  is well defined only for integral values of $n$ greater than or equal to zero.
  There is not even consensus how to define this function for $n<0$. Thus, it is
  not differentiable. Therefore, we need to check whether we erroneously are
***************
*** 275,287 ****
--- 270,355 ----
               + opdsum [differentiate(f, x), d, y, g, h]
  \end{verbatim}
  
+ Up to [[patch--45]] a similar mistake could be found in the code for
+ differentiation of formal sums, which read
+ \begin{verbatim}
+     dvsum(l, x) ==
+       k  := retract(second l)@K
+       differentiate(third l, x) * summand l
+           + opsum [differentiate(first l, x), second l, third l]
+ \end{verbatim}
+ 
+ <<package COMBF CombinatorialFunction>>=
+     dvprod(l, x) ==
+       dm := retract(dummy)@SE
+       f := eval(first l, retract(second l)@K, dm::F)
+       p := product(f, dm)
+ 
+       opsum [differentiate(first l, x)/first l * p, second l, third l]
+ 
+ 
+     dvdprod(l, x) ==
+       x = retract(y := third l)@SE => 0
+       if member?(x, variables(h := third rest rest l)) or 
+          member?(x, variables(g := third rest l)) then
+         error "a product cannot be differentiated with respect to a bound"
+       else
+         opdsum cons(differentiate(first l, x)/first l, rest l) * opdprod l 
+ 
+ @ 
+ The above two operations implement differentiation of products with and without
+ bounds. Note again, that we cannot even properly define products with bounds
+ that are not integral.
+ 
+ To differentiate the product, we use Leibniz rule:
+ $$\frac{d}{dx}\prod_{i=a}^b f(i,x) = 
+   \sum_{i=a}^b \frac{\frac{d}{dx} f(i,x)}{f(i,x)}\prod_{i=a}^b f(i,x)
+ $$
+ 
+ There is one situation where this definition might produce wrong results,
+ namely when the product is zero, but axiom failed to recognize it: in this
+ case,
+ $$
+   \frac{d}{dx} f(i,x)/f(i,x)  
+ $$
+ is undefined for some $i$. However, I was not able to come up with an
+ example. The alternative definition
+ $$
+   \frac{d}{dx}\prod_{i=a}^b f(i,x) = 
+   \sum_{i=a}^b \left(\frac{d}{dx} f(i,x)\right)\prod_{j=a,j\neq i}^b f(j,x)
+ $$
+ has the slight (display) problem that we would have to come up with a new index
+ variable, which looks very ugly. Furthermore, it seems to me that more
+ simplifications will occur with the first definition.
+ 
+ <<TEST COMBF>>=
+   f := operator 'f
+   D(product(f(i,x),i=1..m),x)
+ @
+ 
+ Note that up to [[patch--45]] these functions did not exist and products were
+ differentiated according to the usual chain rule, which gave incorrect
+ results. (Issue~\#211)
+ 
  <<package COMBF CombinatorialFunction>>=
+     dprod l ==
+       prod(summand(l)::O, third(l)::O)
+ 
      ddprod l ==
        prod(summand(l)::O, third(l)::O = fourth(l)::O, fourth(rest l)::O)
  
+     dsum l ==
+       sum(summand(l)::O, third(l)::O)
+ 
      ddsum l ==
        sum(summand(l)::O, third(l)::O = fourth(l)::O, fourth(rest l)::O)
  
+ @ 
+ These four operations handle the conversion of sums and products to
+ [[OutputForm]]. Note that up to [[patch--45]] the definitions for sums and
+ products without bounds were missing and output was illegible.
+ 
+ <<package COMBF CombinatorialFunction>>=
      product(x:F, s:SegmentBinding F) ==
        k := kernel(variable s)$K
        dm := dummy
***************
*** 293,299 ****
        opdsum [eval(x,k,dm), dm, k::F, lo segment s, hi segment s]
  
  @
- 
  These two operations return the product or the sum as unevaluated operators. A
  dummy variable is introduced to make the indexing variable \lq local\rq.
  
--- 361,366 ----
***************
*** 466,488 ****
                      log(first l) * first(l) ** second(l)
  
  @
- 
  This operation implements the differentiation of the power operator [[%power]]
  with respect to its second argument, i.e., the exponent. It uses the formula
! 
! $$\frac{d}{dx} g(y)^x = \frac{d}{dx} e^{x\log g(y)} = \log g(y) g(y)^x$$.
  
  If $g(y)$ equals zero, this formula is not valid, since the logarithm is not
  defined there. Although strictly speaking $0^x$ is not differentiable at zero,
  we return zero for convenience. 
  
  Note that up to [[patch--25]] this used to read
- 
  \begin{verbatim}
      if F has ElementaryFunctionCategory then
        dvpow2 l == log(first l) * first(l) ** second(l)
  \end{verbatim}
- 
  which caused differentiating $0^x$ to fail. (Issue~\#19)
  
  <<package COMBF CombinatorialFunction>>=
--- 533,551 ----
                      log(first l) * first(l) ** second(l)
  
  @
  This operation implements the differentiation of the power operator [[%power]]
  with respect to its second argument, i.e., the exponent. It uses the formula
! $$\frac{d}{dx} g(y)^x = \frac{d}{dx} e^{x\log g(y)} = \log g(y) g(y)^x.$$
  
  If $g(y)$ equals zero, this formula is not valid, since the logarithm is not
  defined there. Although strictly speaking $0^x$ is not differentiable at zero,
  we return zero for convenience. 
  
  Note that up to [[patch--25]] this used to read
  \begin{verbatim}
      if F has ElementaryFunctionCategory then
        dvpow2 l == log(first l) * first(l) ** second(l)
  \end{verbatim}
  which caused differentiating $0^x$ to fail. (Issue~\#19)
  
  <<package COMBF CombinatorialFunction>>=
***************
*** 495,506 ****
      evaluate(opprod, iprod)
      evaluate(opdprod, iidprod)
      derivative(oppow, [dvpow1, dvpow2])
!     setProperty(opsum,SPECIALDIFF,dvsum@((List F,SE) -> F) pretend None)
!     setProperty(opdsum,SPECIALDIFF,dvdsum@((List F,SE)->F) pretend None)
!     setProperty(opdsum,  SPECIALDISP,  ddsum@(List F -> O) pretend None)
      setProperty(opdprod, SPECIALDISP, ddprod@(List F -> O) pretend None)
  
! @
  \section{package FSPECF FunctionalSpecialFunction}
  <<package FSPECF FunctionalSpecialFunction>>=
  )abbrev package FSPECF FunctionalSpecialFunction
--- 558,583 ----
      evaluate(opprod, iprod)
      evaluate(opdprod, iidprod)
      derivative(oppow, [dvpow1, dvpow2])
!     setProperty(opsum,   SPECIALDIFF, dvsum@((List F, SE) -> F) pretend None)
!     setProperty(opdsum,  SPECIALDIFF, dvdsum@((List F, SE)->F) pretend None)
!     setProperty(opprod,  SPECIALDIFF, dvprod@((List F, SE)->F) pretend None)
!     setProperty(opdprod, SPECIALDIFF, dvdprod@((List F, SE)->F) pretend None)
! @
! The last four properties define special differentiation rules for sums and
! products. Note that up to [[patch--45]] the rules for products were missing.
! Thus products were differentiated according the usual chain-rule, which gave
! incorrect results.
! 
! <<package COMBF CombinatorialFunction>>=
!     setProperty(opsum,   SPECIALDISP, dsum@(List F -> O) pretend None)
!     setProperty(opdsum,  SPECIALDISP, ddsum@(List F -> O) pretend None)
!     setProperty(opprod,  SPECIALDISP, dprod@(List F -> O) pretend None)
      setProperty(opdprod, SPECIALDISP, ddprod@(List F -> O) pretend None)
  
! @ 
! Finally, we set the properties for displaying sums and products.
! 
! 
  \section{package FSPECF FunctionalSpecialFunction}
  <<package FSPECF FunctionalSpecialFunction>>=
  )abbrev package FSPECF FunctionalSpecialFunction
