Math-Yapp

 view release on metacpan or  search on metacpan

lib/Math/Yapp.pm  view on Meta::CPAN

    {                                           # degree, then
      $self->{coeff}[$cur_degree] += $cur_coeff; # just add this one
    }
    else                                        # No term of this degree yet
    {                                           # This is new here
      $self->{coeff}[$cur_degree] = $cur_coeff; # Set the coefficient now
    }
  } # End of for-loop to parse individual terms

  # Bug fix (Too lazy to locate screw-up): Somehow I can get this far
  # without a variable component.  So just in case..
  #
  $self->{variable} = "X" if (!defined($self->{variable}));

  return $self;
}
#
#------------------------------------------------------------------------------
# Yapp_plus - Function to implement the += operator
# Parameters:
# - (Implicit) [Reference to] my target object
# - The object to added to my target object. This may be:
#   o Another Yapp polynomial object [reference]
#   o A constant, either real or complex (a different, albeit smaller can
#     of worms)
#
sub Yapp_plus
{
  my ($self, $added) = @_;  # Get relevant parameters. Swap is irrelevant

  # Now, what is $added?
  #
  if (ref($added) eq $class_name)   # If it is another polynomial
  {
    my $alc = 0;                        # Loop counter to step up added terms
    my $new_degree = $self->{degree};   # Track degree in case the added
                                        # polynomial has a higher degree
    my @builder = @{$self->{coeff}};    # Copy coefficients into temporary list
    for ($alc = 0; $alc <= $added->{degree}; $alc++)    # For all terms of the
    {                                                   # added polynomial
      if (defined($builder[$alc]))      # If target has term of this degree
           { $builder[$alc] += $added->{coeff}[$alc]; } # Just add these terms
      else { $builder[$alc]  = $added->{coeff}[$alc]; } # Or copy this term
      $new_degree = $alc if ($alc > $self->{degree});   # Maintain degree
    }
    # Temporary areas have been evaluated. Now plug these into target Yapp
    #
    $self->{degree} = $new_degree;      # Carry over the augmented (?) degree
    @{$self->{coeff}} = @builder;       # and the augmented polynomial
  }                                     # And I have my return value
  elsif (   ($added =~ m/^($coef_pat)$/)
         || (ref($added) eq $class_cplx) )  # Adding real or complex const
  {
    # As above: If the target term is defined, add the new term.
    # Otherwise, set the target term to the given value
    #
    if (defined($self->{coeff}[0])) {$self->{coeff}[0] += $added;}
    else                            {$self->{coeff}[0]  = $added;}
  }         # (Just needed to augment the constant term)
  else
  { die "Operator += requires a constant or a Yapp polynomial reference";}

  # Didn't die - I have a good value to return
  #
  return ($self);                       # (Ought to return something)
}

#------------------------------------------------------------------------------
# Yapp_add() - Function (and overloaded + operator) to add two polynomials.
# Parameters:
# - (Implicit) The polynomial on the left side of the + (self)
# - The polynomial to be added.  This may be:
#   o (Implicit) [A reference to] another Yapp polynomial object
#   o A constant, either real or complex  (See Yapp_plus)
# - (Implicit) The "swapped" flag, largely irrelevant for the + operator
# Returns:
# A reference to a new Yapp polynomial
#
sub Yapp_add
{
  my ($self, $adder, $swapped) = @_;    #(swap is irrelelvant for add)

  my $ryapp = Yapp($self);          # Clone the original
  $ryapp += $adder;                 # Let _plus() function handle details
  return $ryapp;                    # Assume $ryapp will be auto-destroyed?
}
#
#------------------------------------------------------------------------------
# Yapp_minus(): Function (and overloaded -= operator) to subtract the passed
#               polybnomial from the object polynomial in place.  That is,
#               it modifies the $self object
# - (Implicit) [Reference to] my target object
# - The object to added to my target object. This may be:
#   o Another Yapp polynomial object [reference]
#   o A constant, either real or complex
# Returns:
# - The same reference.  But the target Yapp ahs been "deminished"
#
sub Yapp_minus
{
  my ($self, $subtractor) = @_[0 .. 1];

  if (ref($subtractor) eq $class_name)  # Subtracting another polynimal
  {                                     # just use the add method
    my $temp_subt = $subtractor->Yapp_negate(); # Quickie way out: Negate and
                                                # add,  However I cant
    my $temp_self = Yapp($self);                # use -= on $sef. Dunno why
    $temp_self += $temp_subt;                   # Add the negated Yapp
    @{$self->{coeff}} = @{$temp_self->{coeff}}; # Restore subtracted
                                                # coeffiecient array
  }
  else                                  # Otherwise, just assume a constant
  {                                     # be it real or complex.
    # If our polynomial has no constant term, this is it, after negation.
    #
    $self->{coeff}[0] = (defined($self->{coeff}[0]))
                      ? $self->{coeff}[0] - $subtractor
                      : - $subtractor ;
  }
  return $self;
}

lib/Math/Yapp.pm  view on Meta::CPAN

# - (Implicit) The target object ($self)
# - The multiplier.  This may be:
#   o Another Yapp object (Happiest with this parameter type)
#   o A real or complex constant
# Returns:
# The $self-same reference, but it has been "mutated" by the method.
#
sub Yapp_mult
{
  my ($self, $multiplier) = @_;
  my $aux_yapp;             # I may have to create another Yapp
  my $ylc;                  # Loop counter for stepping up coefficients

  # Now what data type is the multiplier?
  #
#Xif (   (ref($multiplier) eq "$class_cplx")    # Complex number constant
#X    || (   (ref(\$multiplier) eq "SCALAR")    # or a scalar that happens
#X        && ($multiplier =~ /^($coef_pat)$/))) # to be a real constant
#X Note: The above logic is good but for very low floating point numbers it
#X was failing to match the corefficient pattern.  Hence, I relaxed the
#X matching requirement.  -- Jacob

  if (   (ref($multiplier)  eq "$class_cplx")   # Complex number constant
      || (ref(\$multiplier) eq "SCALAR"     ) ) # or a scalar (Assume numeric)
  {                                             # Just distribute multiplier
    for ($ylc = 0; $ylc <= $self->{degree}; $ylc++)
    {
      $self->{coeff}[$ylc] *= $multiplier
        if ($self->{coeff}[$ylc] != 0) ;    # Don't bother multiplying 0
    }
  }
  elsif (ref($multiplier) eq $class_name)   # Multiplying by a polynomial
  {
    my @builder = ();                       # Build result area from scratch
    my $new_degree = $self->{degree}
                   + $multiplier->{degree}; # (Remember your 9th grade algebra?)
    for ($ylc = 0; $ylc <= $self->{degree}; $ylc++)
    {                                   # Outer loop multiplies one target term
      for (my $mlc = 0; $mlc <= $multiplier->{degree}; $mlc++)
      {                                 # Inner loop multiplies by one
                                        # multiplier term
        my $term_degree = $ylc + $mlc;      # Degree of this target term
        $builder[$term_degree] = 0.0                # Make sure there is a
          if (! defined($builder[$term_degree]));   # value in here to start

        # Accumulate product term of that degree: Product of the terms whose
        # exponents add up to the [eventual] exponent of this term
        #
        $builder[$term_degree] += $self->{coeff}[$ylc]
                                * $multiplier->{coeff}[$mlc] ;

      }     # End loop multiplying one target term by term from multiplier
    }     # End loop multiplying whole polynomials
    # Done multiplication: Now put it back in place
    #
    $self->{degree} = $new_degree;  # Copy back degree of multiplied target Yapp
    @{$self->{coeff}} = @builder;   # and copy back array where we carried
                                    # out the multiplication.
  }                         # All done multiplying Yapps; product is in place
  else                      # No more permitted possibilities
  { die "Operator *= requires a constant or a Yapp polynomial reference";}

  # Afterthought: I have found that when I multiply two poly's with conjugate
  # complex constant terms, the result will include coefficients like like
  # (30.00+0.00i); which is a real, of course, but doesn't look that way.
  # Here's the fix:
  #
  realify(\@{$self->{coeff}});
  return $self;
}
#
#------------------------------------------------------------------------------
# Yapp_times(): Method to implement the overloaded '*' operator
# Parameters:
# - (Implicit) The operand (usually the left) to the multiplicaton
# - [Reference] to the multiplier, which may be:
#   o Another Yapp object (Happiest with this parameter type)
#   o A real or complex constant
# - Swapped-operands flag, largely irrelevant for multiplication
# Returns:
# - [Reference to] a new Yapp polynomial that is the product of the first
#   two parameters
#
sub Yapp_times
{
  my ($self, $multiplier, $swapped) = @_;
  my $ryapp;                # The object to be returned

  $ryapp = Yapp($self);     # Make a copy
  $ryapp *= $multiplier;    # Carry out operation
  return $ryapp;            #(Wasnt't that simple?)
}
#
#------------------------------------------------------------------------------
# Yapp_power(): Method to implement exponentiation of polynomial by an
#               integer power.
# Parameters:
# - (Implicit) The operand, a ref to the polynomial being multiplied by itself
# - The power, which must be an integer
# - Swapped-operands flag:  grounds for immediate death
# Returns:
# - A [ref to a] Yapp polynomial that is the original raised to the
#   indicated powert
#
sub Yapp_power
{
  my ($self, $power, $swapped) = @_;

  # Some validations:
  #
  die "You cannot raise a number to a polynomial power"
    if ($swapped);
  die "Power must be an integer"
    if ($power != int($power));

  # And now that that's been squared away: Get to work
  #
  my $ryapp = Yapp(1);          # Start with a unit polynomial
  while ($power-- > 0)          # (Decrement after testing)
  {
    $ryapp *= $self;            # Carry out the self-multiplication



( run in 2.094 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )