diff options
author | Nick Ing-Simmons <nik@tiuk.ti.com> | 1998-07-02 18:36:59 +0000 |
---|---|---|
committer | Nick Ing-Simmons <nik@tiuk.ti.com> | 1998-07-02 18:36:59 +0000 |
commit | fc657161c79c5094cda4af53f8d9a4421dfe9959 (patch) | |
tree | 81d1503cdb838e943eb250357f5a52dea20b60c9 | |
parent | 4464c260eb4d110a8ad689e646a8f3f337061a11 (diff) | |
parent | eacd03c1d97275b2758afcdbb834e028f5a3b9d8 (diff) | |
download | perl-fc657161c79c5094cda4af53f8d9a4421dfe9959.tar.gz |
Integrate mainline, just to keep up.
p4raw-id: //depot/ansiperl@1275
-rw-r--r-- | MANIFEST | 2 | ||||
-rw-r--r-- | lib/ExtUtils/MM_Unix.pm | 84 | ||||
-rw-r--r-- | lib/ExtUtils/MakeMaker.pm | 17 | ||||
-rw-r--r-- | lib/Math/Trig.pm | 250 | ||||
-rw-r--r-- | lib/Math/Trig/Radial.pm | 193 | ||||
-rw-r--r-- | lib/base.pm | 35 | ||||
-rw-r--r-- | lib/fields.pm | 131 | ||||
-rw-r--r-- | mg.c | 48 | ||||
-rw-r--r-- | pod/perldiag.pod | 12 | ||||
-rw-r--r-- | pod/perltrap.pod | 27 | ||||
-rw-r--r-- | pp_hot.c | 32 | ||||
-rw-r--r-- | scope.c | 2 | ||||
-rw-r--r-- | scope.h | 35 | ||||
-rwxr-xr-x | t/lib/fields.t | 110 | ||||
-rwxr-xr-x | t/lib/trig.t | 101 | ||||
-rwxr-xr-x | t/op/array.t | 32 | ||||
-rw-r--r-- | toke.c | 4 | ||||
-rw-r--r-- | utils/perldoc.PL | 6 | ||||
-rw-r--r-- | win32/config.bc | 4 | ||||
-rw-r--r-- | win32/config.gc | 4 | ||||
-rw-r--r-- | win32/config.vc | 4 | ||||
-rw-r--r-- | win32/include/dirent.h | 12 | ||||
-rw-r--r-- | win32/makedef.pl | 6 | ||||
-rw-r--r-- | win32/win32.c | 12 | ||||
-rw-r--r-- | win32/win32iop.h | 7 |
25 files changed, 796 insertions, 374 deletions
@@ -481,7 +481,6 @@ lib/Math/BigFloat.pm An arbitrary precision floating-point arithmetic package lib/Math/BigInt.pm An arbitrary precision integer arithmetic package lib/Math/Complex.pm A Complex package lib/Math/Trig.pm A simple interface to complex trigonometry -lib/Math/Trig/Radial.pm Spherical and cylindrical trigonometry lib/Net/Ping.pm Hello, anybody home? lib/Net/hostent.pm By-name interface to Perl's builtin gethost* lib/Net/netent.pm By-name interface to Perl's builtin getnet* @@ -796,6 +795,7 @@ t/lib/dosglob.t See if File::DosGlob works t/lib/english.t See if English works t/lib/env.t See if Env works t/lib/errno.t See if Errno works +t/lib/fields.t See if base/fields works t/lib/filecache.t See if FileCache works t/lib/filecopy.t See if File::Copy works t/lib/filefind.t See if File::Find works diff --git a/lib/ExtUtils/MM_Unix.pm b/lib/ExtUtils/MM_Unix.pm index daa477cd10..6739743da0 100644 --- a/lib/ExtUtils/MM_Unix.pm +++ b/lib/ExtUtils/MM_Unix.pm @@ -5,7 +5,7 @@ use Config; use File::Basename qw(basename dirname fileparse); use DirHandle; use strict; -use vars qw($VERSION $Is_Mac $Is_OS2 $Is_VMS $Is_Win32 $Is_Dos +use vars qw($VERSION $Is_Mac $Is_OS2 $Is_VMS $Is_Win32 $Is_Dos $Is_PERL_OBJECT $Verbose %pm %static $Xsubpp_Version); $VERSION = substr q$Revision: 1.126 $, 10; @@ -19,6 +19,8 @@ $Is_Mac = $^O eq 'MacOS'; $Is_Win32 = $^O eq 'MSWin32'; $Is_Dos = $^O eq 'dos'; +$Is_PERL_OBJECT = 1 if $Config{'ccflags'} =~ /-DPERL_OBJECT/; + if ($Is_VMS = $^O eq 'VMS') { require VMS::Filespec; import VMS::Filespec qw( &vmsify ); @@ -212,6 +214,7 @@ sub ExtUtils::MM_Unix::pm_to_blib ; sub ExtUtils::MM_Unix::post_constants ; sub ExtUtils::MM_Unix::post_initialize ; sub ExtUtils::MM_Unix::postamble ; +sub ExtUtils::MM_Unix::ppd ; sub ExtUtils::MM_Unix::prefixify ; sub ExtUtils::MM_Unix::processPL ; sub ExtUtils::MM_Unix::realclean ; @@ -371,7 +374,7 @@ sub cflags { $self->{uc $_} ||= $cflags{$_} } - if ($self->{CAPI}) { + if ($self->{CAPI} && $Is_PERL_OBJECT == 1) { $self->{CCFLAGS} =~ s/-DPERL_OBJECT(\s|$)//; $self->{CCFLAGS} .= '-DPERL_CAPI'; if ($Is_Win32 && $Config{'cc'} =~ /^cl.exe/i) { @@ -2596,6 +2599,32 @@ sub parse_version { return $result; } +=item parse_abstract + +parse a file and return what you think is the ABSTRACT + +=cut + +sub parse_abstract { + my($self,$parsefile) = @_; + my $result; + local *FH; + local $/ = "\n"; + open(FH,$parsefile) or die "Could not open '$parsefile': $!"; + my $inpod = 0; + my $package = $self->{DISTNAME}; + $package =~ s/-/::/; + while (<FH>) { + $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod; + next if !$inpod; + chop; + next unless /^($package\s-\s)(.*)/; + $result = $2; + last; + } + close FH; + return $result; +} =item pasthru (o) @@ -2695,6 +2724,57 @@ $(OBJECT) : $(PERL_HDRS) join "\n", @m; } +=item ppd + +Defines target that creates a PPD (Perl Package Description) file +for a binary distribution. + +=cut + +sub ppd { + my($self) = @_; + my(@m); + if ($self->{ABSTRACT_FROM}){ + $self->{ABSTRACT} = $self->parse_abstract($self->{ABSTRACT_FROM}) or + Carp::carp "WARNING: Setting ABSTRACT via file '$self->{ABSTRACT_FROM}' failed\n"; + } + my ($pack_ver) = join ",", (split (/\./, $self->{VERSION}), (0) x 4) [0 .. 3]; + push(@m, "# Creates a PPD (Perl Package Description) for a binary distribution.\n"); + push(@m, "ppd:\n"); + push(@m, "\t\@\$(PERL) -e \"print qq{<SOFTPKG NAME=\\\"$self->{DISTNAME}\\\" VERSION=\\\"$pack_ver\\\">\\n}"); + push(@m, ". qq{\\t<TITLE>$self->{DISTNAME}</TITLE>\\n}"); + my $abstract = $self->{ABSTRACT}; + $abstract =~ s/</</g; + $abstract =~ s/>/>/g; + push(@m, ". qq{\\t<ABSTRACT>$abstract</ABSTRACT>\\n}"); + my ($author) = $self->{AUTHOR}; + $author =~ s/@/\\@/g; + push(@m, ". qq{\\t<AUTHOR>$author</AUTHOR>\\n}"); + push(@m, ". qq{\\t<IMPLEMENTATION>\\n}"); + my ($prereq); + foreach $prereq (sort keys %{$self->{PREREQ_PM}}) { + my $pre_req = $prereq; + $pre_req =~ s/::/-/g; + push(@m, ". qq{\\t\\t<DEPENDENCY NAME=\\\"$pre_req\\\" />\\n}"); + } + push(@m, ". qq{\\t\\t<OS NAME=\\\"\$(OSNAME)\\\" />\\n}"); + my ($bin_location) = $self->{BINARY_LOCATION}; + $bin_location =~ s/\\/\\\\/g; + if ($self->{PPM_INSTALL_SCRIPT}) { + if ($self->{PPM_INSTALL_EXEC}) { + push(@m, " . qq{\\t\\t<INSTALL EXEC=\\\"$self->{PPM_INSTALL_EXEC}\\\">$self->{PPM_INSTALL_SCRIPT}</INSTALL>\\n}"); + } + else { + push(@m, " . qq{\\t\\t<INSTALL>$self->{PPM_INSTALL_SCRIPT}</INSTALL>\\n}"); + } + } + push(@m, ". qq{\\t\\t<CODEBASE HREF=\\\"$bin_location\\\" />\\n}"); + push(@m, ". qq{\\t</IMPLEMENTATION>\\n}"); + push(@m, ". qq{</SOFTPKG>\\n}\" > $self->{DISTNAME}.ppd"); + + join("", @m); +} + =item perm_rw (o) Returns the attribute C<PERM_RW> or the string C<644>. diff --git a/lib/ExtUtils/MakeMaker.pm b/lib/ExtUtils/MakeMaker.pm index eac32ace23..375a699c49 100644 --- a/lib/ExtUtils/MakeMaker.pm +++ b/lib/ExtUtils/MakeMaker.pm @@ -73,6 +73,10 @@ $Is_OS2 = $^O eq 'os2'; $Is_Mac = $^O eq 'MacOS'; $Is_Win32 = $^O eq 'MSWin32'; +# This is for module authors to query, so they can enable 'CAPI' => 'TRUE' +# in their Makefile.pl +$CAPI_support = 1; + require ExtUtils::MM_Unix; if ($Is_VMS) { @@ -235,7 +239,7 @@ sub full_setup { @Attrib_help = qw/ - CAPI + AUTHOR ABSTRACT ABSTRACT_FROM BINARY_LOCATION LICENSE_HREF CAPI C CCFLAGS CONFIG CONFIGURE DEFINE DIR DISTNAME DL_FUNCS DL_VARS EXE_FILES EXCLUDE_EXT INCLUDE_EXT NO_VC FIRST_MAKEFILE FULLPERL H INC INSTALLARCHLIB INSTALLBIN INSTALLDIRS INSTALLMAN1DIR @@ -248,7 +252,7 @@ sub full_setup { PL_FILES PM PMLIBDIRS PREFIX PREREQ_PM SKIP TYPEMAPS VERSION VERSION_FROM XS XSOPT XSPROTOARG XS_VERSION clean depend dist dynamic_lib linkext macro realclean - tool_autosplit + tool_autosplit PPM_INSTALL_SCRIPT PPM_INSTALL_EXEC IMPORTS @@ -280,7 +284,7 @@ sub full_setup { c_o xs_c xs_o top_targets linkext dlsyms dynamic dynamic_bs dynamic_lib static static_lib manifypods processPL installbin subdirs clean realclean dist_basics dist_core dist_dir dist_test dist_ci - install force perldepend makefile staticmake test + install force perldepend makefile staticmake test ppd ); # loses section ordering @@ -309,7 +313,7 @@ sub full_setup { @Get_from_Config = qw( ar cc cccdlflags ccdlflags dlext dlsrc ld lddlflags ldflags libc - lib_ext obj_ext ranlib sitelibexp sitearchexp so exe_ext + lib_ext obj_ext osname osvers ranlib sitelibexp sitearchexp so exe_ext ); my $item; @@ -383,8 +387,9 @@ sub ExtUtils::MakeMaker::new { eval $eval; if ($@){ warn "Warning: prerequisite $prereq $self->{PREREQ_PM}->{$prereq} not found"; - } else { - delete $self->{PREREQ_PM}{$prereq}; +# Why is/was this 'delete' here? We need PREREQ_PM later to make PPDs. +# } else { +# delete $self->{PREREQ_PM}{$prereq}; } } # if (@unsatisfied){ diff --git a/lib/Math/Trig.pm b/lib/Math/Trig.pm index a1cbb07234..7192d76fe9 100644 --- a/lib/Math/Trig.pm +++ b/lib/Math/Trig.pm @@ -1,6 +1,6 @@ # # Trigonometric functions, mostly inherited from Math::Complex. -# -- Jarkko Hietaniemi, April 1997 +# -- Jarkko Hietaniemi, since April 1997 # -- Raphael Manfredi, September 1996 (indirectly: because of Math::Complex) # @@ -13,7 +13,7 @@ use Math::Complex qw(:trig); use vars qw($VERSION $PACKAGE @ISA - @EXPORT); + @EXPORT @EXPORT_OK %EXPORT_TAGS); @ISA = qw(Exporter); @@ -26,13 +26,25 @@ my @angcnv = qw(rad2deg rad2grad @EXPORT = (@{$Math::Complex::EXPORT_TAGS{'trig'}}, @angcnv); -use constant pi2 => 2 * pi; -use constant DR => pi2/360; -use constant RD => 360/pi2; -use constant DG => 400/360; -use constant GD => 360/400; -use constant RG => 400/pi2; -use constant GR => pi2/400; +my @rdlcnv = qw(cartesian_to_cylindrical + cartesian_to_spherical + cylindrical_to_cartesian + cylindrical_to_spherical + spherical_to_cartesian + spherical_to_cylindrical); + +@EXPORT_OK = (@rdlcnv, 'great_circle_distance'); + +%EXPORT_TAGS = ('radial' => [ @rdlcnv ]); + +use constant pi2 => 2 * pi; +use constant pip2 => pi / 2; +use constant DR => pi2/360; +use constant RD => 360/pi2; +use constant DG => 400/360; +use constant GD => 360/400; +use constant RG => 400/pi2; +use constant GR => pi2/400; # # Truncating remainder. @@ -59,6 +71,61 @@ sub rad2grad ($) { remt(RG * $_[0], 400) } sub grad2rad ($) { remt(GR * $_[0], pi2) } +sub cartesian_to_spherical { + my ( $x, $y, $z ) = @_; + + my $rho = sqrt( $x * $x + $y * $y + $z * $z ); + + return ( $rho, + atan2( $y, $x ), + $rho ? acos( $z / $rho ) : 0 ); +} + +sub spherical_to_cartesian { + my ( $rho, $theta, $phi ) = @_; + + return ( $rho * cos( $theta ) * sin( $phi ), + $rho * sin( $theta ) * sin( $phi ), + $rho * cos( $phi ) ); +} + +sub spherical_to_cylindrical { + my ( $x, $y, $z ) = spherical_to_cartesian( @_ ); + + return ( sqrt( $x * $x + $y * $y ), $_[1], $z ); +} + +sub cartesian_to_cylindrical { + my ( $x, $y, $z ) = @_; + + return ( sqrt( $x * $x + $y * $y ), atan2( $y, $x ), $z ); +} + +sub cylindrical_to_cartesian { + my ( $rho, $theta, $z ) = @_; + + return ( $rho * cos( $theta ), $rho * sin( $theta ), $z ); +} + +sub cylindrical_to_spherical { + return ( cartesian_to_spherical( cylindrical_to_cartesian( @_ ) ) ); +} + +sub great_circle_distance { + my ( $theta0, $phi0, $theta1, $phi1, $rho ) = @_; + + $rho = 1 unless defined $rho; # Default to the unit sphere. + + my $lat0 = pip2 - $phi0; + my $lat1 = pip2 - $phi1; + + return $rho * + acos(cos( $lat0 ) * cos( $lat1 ) * cos( $theta0 - $theta1 ) + + sin( $lat0 ) * sin( $lat1 ) ); +} + +=pod + =head1 NAME Math::Trig - trigonometric functions @@ -86,68 +153,72 @@ conversions. The tangent - tan +=over 4 + +=item B<tan> + +=back The cofunctions of the sine, cosine, and tangent (cosec/csc and cotan/cot are aliases) - csc cosec sec cot cotan +B<csc>, B<cosec>, B<sec>, B<sec>, B<cot>, B<cotan> The arcus (also known as the inverse) functions of the sine, cosine, and tangent - asin acos atan +B<asin>, B<acos>, B<atan> The principal value of the arc tangent of y/x - atan2(y, x) +B<atan2>(y, x) The arcus cofunctions of the sine, cosine, and tangent (acosec/acsc and acotan/acot are aliases) - acsc acosec asec acot acotan +B<acsc>, B<acosec>, B<asec>, B<acot>, B<acotan> The hyperbolic sine, cosine, and tangent - sinh cosh tanh +B<sinh>, B<cosh>, B<tanh> The cofunctions of the hyperbolic sine, cosine, and tangent (cosech/csch and cotanh/coth are aliases) - csch cosech sech coth cotanh +B<csch>, B<cosech>, B<sech>, B<coth>, B<cotanh> The arcus (also known as the inverse) functions of the hyperbolic sine, cosine, and tangent - asinh acosh atanh +B<asinh>, B<acosh>, B<atanh> The arcus cofunctions of the hyperbolic sine, cosine, and tangent (acsch/acosech and acoth/acotanh are aliases) - acsch acosech asech acoth acotanh +B<acsch>, B<acosech>, B<asech>, B<acoth>, B<acotanh> The trigonometric constant B<pi> is also defined. - $pi2 = 2 * pi; +$pi2 = 2 * B<pi>; =head2 ERRORS DUE TO DIVISION BY ZERO The following functions - tan - sec - csc - cot - asec + acoth acsc - tanh - sech - csch - coth - atanh - asech acsch - acoth + asec + asech + atanh + cot + coth + csc + csch + sec + sech + tan + tanh cannot be computed for all arguments because that would mean dividing by zero or taking logarithm of zero. These situations cause fatal @@ -196,7 +267,7 @@ should produce something like this (take or leave few last decimals): That is, a complex number with the real part of approximately C<1.571> and the imaginary part of approximately C<-1.317>. -=head1 ANGLE CONVERSIONS +=head1 PLANE ANGLE CONVERSIONS (Plane, 2-dimensional) angles may be converted with the following functions. @@ -211,6 +282,121 @@ and the imaginary part of approximately C<-1.317>. The full circle is 2 I<pi> radians or I<360> degrees or I<400> gradians. +=head1 RADIAL COORDINATE CONVERSIONS + +B<Radial coordinate systems> are the B<spherical> and the B<cylindrical> +systems, explained shortly in more detail. + +You can import radial coordinate conversion functions by using the +C<:radial> tag: + + use Math::Trig ':radial'; + + ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z); + ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z); + ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z); + ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z); + ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi); + ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi); + +B<All angles are in radians>. + +=head2 COORDINATE SYSTEMS + +B<Cartesian> coordinates are the usual rectangular I<(x, y, +z)>-coordinates. + +Spherical coordinates, I<(rho, theta, pi)>, are three-dimensional +coordinates which define a point in three-dimensional space. They are +based on a sphere surface. The radius of the sphere is B<rho>, also +known as the I<radial> coordinate. The angle in the I<xy>-plane +(around the I<z>-axis) is B<theta>, also known as the I<azimuthal> +coordinate. The angle from the I<z>-axis is B<phi>, also known as the +I<polar> coordinate. The `North Pole' is therefore I<0, 0, rho>, and +the `Bay of Guinea' (think of the missing big chunk of Africa) I<0, +pi/2, rho>. + +B<Beware>: some texts define I<theta> and I<phi> the other way round, +some texts define the I<phi> to start from the horizontal plane, some +texts use I<r> in place of I<rho>. + +Cylindrical coordinates, I<(rho, theta, z)>, are three-dimensional +coordinates which define a point in three-dimensional space. They are +based on a cylinder surface. The radius of the cylinder is B<rho>, +also known as the I<radial> coordinate. The angle in the I<xy>-plane +(around the I<z>-axis) is B<theta>, also known as the I<azimuthal> +coordinate. The third coordinate is the I<z>, pointing up from the +B<theta>-plane. + +=head2 3-D ANGLE CONVERSIONS + +Conversions to and from spherical and cylindrical coordinates are +available. Please notice that the conversions are not necessarily +reversible because of the equalities like I<pi> angles being equal to +I<-pi> angles. + +=over 4 + +=item cartesian_to_cylindrical + + ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z); + +=item cartesian_to_spherical + + ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z); + +=item cylindrical_to_cartesian + + ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z); + +=item cylindrical_to_spherical + + ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z); + +Notice that when C<$z> is not 0 C<$rho_s> is not equal to C<$rho_c>. + +=item spherical_to_cartesian + + ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi); + +=item spherical_to_cylindrical + + ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi); + +Notice that when C<$z> is not 0 C<$rho_c> is not equal to C<$rho_s>. + +=back + +=head1 GREAT CIRCLE DISTANCES + +You can compute spherical distances, called B<great circle distances>, +by importing the C<great_circle_distance> function: + + use Math::Trig 'great_circle_distance' + + $distance = great_circle_distance($theta0, $phi0, $theta1, $phi, [, $rho]); + +The I<great circle distance> is the shortest distance between two +points on a sphere. The distance is in C<$rho> units. The C<$rho> is +optional, it defaults to 1 (the unit sphere), therefore the distance +defaults to radians. + +=head EXAMPLES + +To calculate the distance between London (51.3N 0.5W) and Tokyo (35.7N +139.8E) in kilometers: + + use Math::Trig qw(great_circle_distance deg2rad); + + # Notice the 90 - latitude: phi zero is at the North Pole. + @L = (deg2rad(-0.5), deg2rad(90 - 51.3)); + @T = (deg2rad(139.8),deg2rad(90 - 35.7)); + + $km = great_circle_distance(@L, @T, 6378); + +The answer may be off by up to 0.3% because of the irregular (slightly +aspherical) form of the Earth. + =head1 BUGS Saying C<use Math::Trig;> exports many mathematical routines in the diff --git a/lib/Math/Trig/Radial.pm b/lib/Math/Trig/Radial.pm deleted file mode 100644 index 0001cb7323..0000000000 --- a/lib/Math/Trig/Radial.pm +++ /dev/null @@ -1,193 +0,0 @@ -package Math::Trig::Radial; - -use strict; -use vars qw(@ISA @EXPORT); -@ISA = qw(Exporter); - -@EXPORT = - qw( - cartesian_to_cylindrical - cartesian_to_spherical - cylindrical_to_cartesian - cylindrical_to_spherical - spherical_to_cartesian - spherical_to_cylindrical - great_circle_distance - ); - -use Math::Trig; - -sub pip2 { pi/2 } - -=pod - -=head1 NAME - -Math::Trig::Radial - spherical and cylindrical trigonometry - -=head1 SYNOPSIS - - use Math::Trig::Radial; - - ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z); - ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z); - ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z); - ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z); - ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi); - ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi); - -=head1 DESCRIPTION - -This module contains a few basic spherical and cylindrical -trigonometric formulas. B<All angles are in radians>, if needed -use C<Math::Trig> angle unit conversions. - -=head2 COORDINATE SYSTEMS - -B<Cartesian> coordinates are the usual rectangular I<xyz>-coordinates. - -Spherical coordinates are three-dimensional coordinates which define a -point in three-dimensional space. They are based on a sphere surface. -The radius of the sphere is B<rho>, also known as the I<radial> -coordinate. The angle in the I<xy>-plane (around the I<z>-axis) is -B<theta>, also known as the I<azimuthal> coordinate. The angle from -the I<z>-axis is B<phi>, also known as the I<polar> coordinate. The -`North Pole' is therefore I<0, 0, rho>, and the `Bay of Guinea' (think -Africa) I<0, pi/2, rho>. - -Cylindrical coordinates are three-dimensional coordinates which define -a point in three-dimensional space. They are based on a cylinder -surface. The radius of the cylinder is B<rho>, also known as the -I<radial> coordinate. The angle in the I<xy>-plane (around the -I<z>-axis) is B<theta>, also known as the I<azimuthal> coordinate. -The third coordinate is the I<z>. - -=head2 CONVERSIONS - -Conversions to and from spherical and cylindrical coordinates are -available. Please notice that the conversions are not necessarily -reversible because of the equalities like I<pi> angles equals I<-pi> -angles. - -=over 4 - -=item cartesian_to_cylindrical - - ($rho, $theta, $z) = cartesian_to_cylindrical($x, $y, $z); - -=item cartesian_to_spherical - - ($rho, $theta, $phi) = cartesian_to_spherical($x, $y, $z); - -=item cylindrical_to_cartesian - - ($x, $y, $z) = cylindrical_to_cartesian($rho, $theta, $z); - -=item cylindrical_to_spherical - - ($rho_s, $theta, $phi) = cylindrical_to_spherical($rho_c, $theta, $z); - -Notice that when C<$z> is not 0 C<$rho_s> is not equal to C<$rho_c>. - -=item spherical_to_cartesian - - ($x, $y, $z) = spherical_to_cartesian($rho, $theta, $phi); - -=item spherical_to_cylindrical - - ($rho_c, $theta, $z) = spherical_to_cylindrical($rho_s, $theta, $phi); - -Notice that when C<$z> is not 0 C<$rho_c> is not equal to C<$rho_s>. - -=back - -=head2 GREAT CIRCLE DISTANCE - - $distance = great_circle_distance($x0, $y0, $z0, $x1, $y1, $z1 [, $rho]); - -The I<great circle distance> is the shortest distance between two -points on a sphere. The distance is in C<$rho> units. The C<$rho> is -optional, it defaults to 1 (the unit sphere), therefore the distance -defaults to radians. The coordinates C<$x0> ... C<$z1> are in -cartesian coordinates. - -=head EXAMPLES - -To calculate the distance between London (51.3N 0.5W) and Tokyo (35.7N -139.8E) in kilometers: - - use Math::Trig::Radial; - use Math::Trig; - - my @L = spherical_to_cartesian(1, map { deg2rad $_ } qw(51.3 -0.5)); - my @T = spherical_to_cartesian(1, map { deg2rad $_ } qw(35.7 139.8)); - - $km = great_circle_distance(@L, @T, 6378); - -The answer may be off by up to 0.3% because of the irregular (slightly -aspherical) form of the Earth. - -=head2 AUTHOR - -Jarkko Hietaniemi F<E<lt>jhi@iki.fiE<gt>> - -=cut - -sub cartesian_to_spherical { - my ( $x, $y, $z ) = @_; - - my $rho = sqrt( $x * $x + $y * $y + $z * $z ); - - return ( $rho, - atan2( $y, $x ), - $rho ? acos( $z / $rho ) : 0 ); -} - -sub spherical_to_cartesian { - my ( $rho, $theta, $phi ) = @_; - - return ( $rho * cos( $theta ) * sin( $phi ), - $rho * sin( $theta ) * sin( $phi ), - $rho * cos( $phi ) ); -} - -sub spherical_to_cylindrical { - my ( $x, $y, $z ) = spherical_to_cartesian( @_ ); - - return ( sqrt( $x * $x + $y * $y ), $_[1], $z ); -} - -sub cartesian_to_cylindrical { - my ( $x, $y, $z ) = @_; - - return ( sqrt( $x * $x + $y * $y ), atan2( $y, $x ), $z ); -} - -sub cylindrical_to_cartesian { - my ( $rho, $theta, $z ) = @_; - - return ( $rho * cos( $theta ), $rho * sin( $theta ), $z ); -} - -sub cylindrical_to_spherical { - return ( cartesian_to_spherical( cylindrical_to_cartesian( @_ ) ) ); -} - -sub great_circle_distance { - my ( $x0, $y0, $z0, $x1, $y1, $z1, $rho ) = @_; - - $rho = 1 unless defined $rho; # Default to the unit sphere. - - my ( $r0, $theta0, $phi0 ) = cartesian_to_spherical( $x0, $y0, $z0 ); - my ( $r1, $theta1, $phi1 ) = cartesian_to_spherical( $x1, $y1, $z1 ); - - my $lat0 = pip2 - $phi0; - my $lat1 = pip2 - $phi1; - - return $rho * - acos(cos( $lat0 ) * cos( $lat1 ) * cos( $theta0 - $theta1 ) + - sin( $lat0 ) * sin( $lat1 ) ); -} - -1; - diff --git a/lib/base.pm b/lib/base.pm index 4c4fb8b86b..3500cbfb89 100644 --- a/lib/base.pm +++ b/lib/base.pm @@ -5,7 +5,6 @@ base - Establish IS-A relationship with base class at compile time =head1 SYNOPSIS package Baz; - use base qw(Foo Bar); =head1 DESCRIPTION @@ -18,11 +17,19 @@ Roughly similar in effect to push @ISA, qw(Foo Bar); } +Will also initialize the %FIELDS hash if one of the base classes has +it. Multiple inheritance of %FIELDS is not supported. The 'base' +pragma will croak if multiple base classes has a %FIELDS hash. See +L<fields> for a description of this feature. + +When strict 'vars' is in scope I<base> also let you assign to @ISA +without having to declare @ISA with the 'vars' pragma first. + This module was introduced with Perl 5.004_04. -=head1 BUGS +=head1 SEE ALSO -Needs proper documentation! +L<fields> =cut @@ -30,6 +37,7 @@ package base; sub import { my $class = shift; + my $fields_base; foreach my $base (@_) { unless (defined %{"$base\::"}) { @@ -44,9 +52,26 @@ sub import { "which defines that package first.)"); } } + + # A simple test like (defined %{"$base\::FIELDS"}) will + # sometimes produce typo warnings because it would create + # the hash if it was not present before. + my $fglob; + if ($fglob = ${"$base\::"}{"FIELDS"} and *$fglob{HASH}) { + if ($fields_base) { + require Carp; + Carp::croak("Can't multiply inherit %FIELDS"); + } else { + $fields_base = $base; + } + } + } + my $pkg = caller(0); + push @{"$pkg\::ISA"}, @_; + if ($fields_base) { + require fields; + fields::inherit($pkg, $fields_base); } - - push @{caller(0) . '::ISA'}, @_; } 1; diff --git a/lib/fields.pm b/lib/fields.pm index c2cf1d6a5d..2c75ff4e61 100644 --- a/lib/fields.pm +++ b/lib/fields.pm @@ -8,7 +8,7 @@ fields - compile-time class fields { package Foo; - use fields qw(foo bar baz); + use fields qw(foo bar _private); } ... my Foo $var = new Foo; @@ -17,25 +17,140 @@ fields - compile-time class fields # This will generate a compile-time error. $var->{zap} = 42; + { + package Bar; + use base 'Foo'; + use fields 'bar'; # hides Foo->{bar} + use fields qw(baz _private); # not shared with Foo + } + =head1 DESCRIPTION -The C<fields> pragma enables compile-time verified class fields. +The C<fields> pragma enables compile-time verified class fields. It +does so by updating the %FIELDS hash in the calling package. + +If a typed lexical variable holding a reference is used to access a +hash element and the %FIELDS hash of the given type exists, then the +operation is turned into an array access at compile time. The %FIELDS +hash map from hash element names to the array indices. If the hash +element is not present in the %FIELDS hash, then a compile-time error +is signaled. + +Since the %FIELDS hash is used at compile-time, it must be set up at +compile-time too. This is made easier with the help of the 'fields' +and the 'base' pragma modules. The 'base' pragma will copy fields +from base classes and the 'fields' pragma adds new fields. Field +names that start with an underscore character are made private to a +class and are not visible to subclasses. Inherited fields can be +overridden but will generate a warning if used together with the -w +option. + +The effect of all this is that you can have objects with named fields +which are as compact and as fast arrays too access. This only works +as long as the objects are accessed through properly typed variables. +For untyped access to work you have to make sure that a reference to +the proper %FIELDS hash is assigned to the 0'th element of the array +object (so that the objects can be treated like an AVHV). A +constructor like this does the job: + + sub new + { + my $class = shift; + no strict 'refs'; + my $self = bless [\%{"$class\::FIELDS"], $class; + $self; + } + + +=head1 SEE ALSO + +L<base>, +I<description of AVHVs> =cut +use strict; +no strict 'refs'; +use vars qw(%attr $VERSION); + +$VERSION = "0.02"; + +# some constants +sub _PUBLIC () { 1 } +sub _PRIVATE () { 2 } +sub _INHERITED () { 4 } + +# The %attr hash holds the attributes of the currently assigned fields +# per class. The hash is indexed by class names and the hash value is +# an array reference. The array is indexed with the field numbers +# (minus one) and the values are integer bit masks (or undef). The +# size of the array also indicate the next field index too assign for +# additional fields in this class. + sub import { my $class = shift; - my ($package) = caller; + my $package = caller(0); my $fields = \%{"$package\::FIELDS"}; - my $i = $fields->{__MAX__}; + my $fattr = ($attr{$package} ||= []); + foreach my $f (@_) { - if (defined($fields->{$f})) { + if (my $fno = $fields->{$f}) { require Carp; - Carp::croak("Field name $f already in use"); + if ($fattr->[$fno-1] & _INHERITED) { + Carp::carp("Hides field '$f' in base class") if $^W; + } else { + Carp::croak("Field name '$f' already in use"); + } } - $fields->{$f} = ++$i; + $fields->{$f} = @$fattr + 1; + push(@$fattr, ($f =~ /^_/) ? _PRIVATE : _PUBLIC); } - $fields->{__MAX__} = $i; +} + +sub inherit # called by base.pm +{ + my($derived, $base) = @_; + + if (defined %{"$derived\::FIELDS"}) { + require Carp; + Carp::croak("Inherited %FIELDS can't override existing %FIELDS"); + } else { + my $base_fields = \%{"$base\::FIELDS"}; + my $derived_fields = \%{"$derived\::FIELDS"}; + + $attr{$derived}[@{$attr{$base}}-1] = undef; + while (my($k,$v) = each %$base_fields) { + next if $attr{$base}[$v-1] & _PRIVATE; + $attr{$derived}[$v-1] = _INHERITED; + $derived_fields->{$k} = $v; + } + } + +} + +sub _dump # sometimes useful for debugging +{ + for my $pkg (sort keys %attr) { + print "\n$pkg"; + if (defined @{"$pkg\::ISA"}) { + print " (", join(", ", @{"$pkg\::ISA"}), ")"; + } + print "\n"; + my $fields = \%{"$pkg\::FIELDS"}; + for my $f (sort {$fields->{$a} <=> $fields->{$b}} keys %$fields) { + my $no = $fields->{$f}; + print " $no: $f"; + my $fattr = $attr{$pkg}[$no-1]; + if (defined $fattr) { + my @a; + push(@a, "public") if $fattr & _PUBLIC; + push(@a, "private") if $fattr & _PRIVATE; + push(@a, "inherited") if $fattr & _INHERITED; + print "\t(", join(", ", @a), ")"; + } + print "\n"; + } + } } 1; @@ -899,55 +899,7 @@ magic_setsig(SV *sv, MAGIC *mg) int magic_setisa(SV *sv, MAGIC *mg) { - HV *stash; - SV **svp; - I32 fill; - HV *basefields = Nullhv; - GV **gvp; - GV *gv; - HE *he; - static char *FIELDS = "FIELDS"; - sub_generation++; - - if (mg->mg_type == 'i') - return 0; /* Ignore lower-case version of the magic */ - - stash = GvSTASH(mg->mg_obj); - svp = AvARRAY((AV*)sv); - - /* NOTE: No support for tied ISA */ - for (fill = AvFILLp((AV*)sv); fill >= 0; fill--, svp++) { - HV *basestash = gv_stashsv(*svp, FALSE); - - if (!basestash) { - if (dowarn) - warn("No such package \"%_\" in @ISA assignment", *svp); - continue; - } - gvp = (GV**)hv_fetch(basestash, FIELDS, 6, FALSE); - if (gvp && *gvp && GvHV(*gvp)) { - if (basefields) - croak("Can't multiply inherit %%FIELDS"); - basefields = GvHV(*gvp); - } - } - - if (!basefields) - return 0; - - gv = (GV*)*hv_fetch(stash, FIELDS, 6, TRUE); - if (!isGV(gv)) - gv_init(gv, stash, FIELDS, 6, TRUE); - if (!GvHV(gv)) - GvHV(gv) = newHV(); - if (HvKEYS(GvHV(gv))) - croak("Inherited %%FIELDS can't override existing %%FIELDS"); - - hv_iterinit(GvHV(gv)); - while ((he = hv_iternext(basefields))) - hv_store(GvHV(gv), HeKEY(he), HeKLEN(he), HeVAL(he), HeHASH(he)); - return 0; } diff --git a/pod/perldiag.pod b/pod/perldiag.pod index b58885609b..841be546a6 100644 --- a/pod/perldiag.pod +++ b/pod/perldiag.pod @@ -316,6 +316,11 @@ system malloc(). (P) One of the internal hash routines was passed a null HV pointer. +=item Bad index while coercing array into hash + +(F) A field name of a typed variable was looked up in the %FIELDS +hash, but the index found was not legal, i.e. less than 1. + =item Bad name after %s:: (F) You started to name a symbol by using a package prefix, and then didn't @@ -1601,6 +1606,13 @@ your system. (F) The argument to B<-I> must follow the B<-I> immediately with no intervening space. +=item No such field "%s" in variable %s of type %s + +(F) You tried to access a field of a typed variable where the type +does not know about the field name. The field names are looked up in +the %FIELDS hash in the type package at compile time. The %FIELDS hash +is usually set up with the 'fields' pragma. + =item No such pipe open (P) An error peculiar to VMS. The internal routine my_pclose() tried to diff --git a/pod/perltrap.pod b/pod/perltrap.pod index 4159777146..8a3e3bcdab 100644 --- a/pod/perltrap.pod +++ b/pod/perltrap.pod @@ -921,6 +921,10 @@ Probably a bug. Perl4-to-Perl5 traps involving precedence order. +Perl 4 has almost the same precedence rules as Perl 5 for the operators +that they both have. Perl 4 however, seems to have had some +inconsistencies that made the behavior differ from what was documented. + =over 5 =item * Precedence @@ -996,13 +1000,34 @@ treats C<$::> as main C<package> =item * Precedence -concatenation precedence over filetest operator? +perl4 had buggy precedence for the file test operators vis-a-vis +the assignment operators. Thus, although the precedence table +for perl4 leads one to believe C<-e $foo .= "q"> should parse as +C<((-e $foo) .= "q")>, it actually parses as C<(-e ($foo .= "q"))>. +In perl5, the precedence is as documented. -e $foo .= "q" # perl4 prints: no output # perl5 prints: Can't modify -e in concatenation +=item * Precedence + +In perl4, keys(), each() and values() were special high-precedence operators +that operated on a single hash, but in perl5, they are regular named unary +operators. As documented, named unary operators have lower precedence +than the arithmetic and concatenation operators C<+ - .>, but the perl4 +variants of these operators actually bind tighter than C<+ - .>. +Thus, for: + + %foo = 1..10; + print keys %foo - 1 + + # perl4 prints: 4 + # perl5 prints: Type of arg 1 to keys must be hash (not subtraction) + +The perl4 behavior was probably more useful, if less consistent. + =back =head2 General Regular Expression Traps using s///, etc. @@ -626,7 +626,6 @@ PP(pp_aassign) hv_clear(hash); while (relem < lastrelem) { /* gobble up all the rest */ - STRLEN len; HE *didstore; if (*relem) sv = *(relem++); @@ -645,14 +644,29 @@ PP(pp_aassign) } TAINT_NOT; } - if (relem == lastrelem && dowarn) { - if (relem == firstrelem && - SvROK(*relem) && - ( SvTYPE(SvRV(*relem)) == SVt_PVAV || - SvTYPE(SvRV(*relem)) == SVt_PVHV ) ) - warn("Reference found where even-sized list expected"); - else - warn("Odd number of elements in hash assignment"); + if (relem == lastrelem) { + if (*relem) { + HE *didstore; + if (dowarn) { + if (relem == firstrelem && + SvROK(*relem) && + ( SvTYPE(SvRV(*relem)) == SVt_PVAV || + SvTYPE(SvRV(*relem)) == SVt_PVHV ) ) + warn("Reference found where even-sized list expected"); + else + warn("Odd number of elements in hash assignment"); + } + tmpstr = NEWSV(29,0); + didstore = hv_store_ent(hash,*relem,tmpstr,0); + if (magic) { + if (SvSMAGICAL(tmpstr)) + mg_set(tmpstr); + if (!didstore) + SvREFCNT_dec(tmpstr); + } + TAINT_NOT; + } + relem++; } } break; @@ -806,7 +806,7 @@ leave_scope(I32 base) case SAVEt_OP: op = (OP*)SSPOPPTR; break; - case SAVEt_NOHINTS: + case SAVEt_HINTS: if (GvHV(hintgv)) { SvREFCNT_dec((SV*)GvHV(hintgv)); GvHV(hintgv) = NULL; @@ -25,7 +25,7 @@ #define SAVEt_AELEM 24 #define SAVEt_HELEM 25 #define SAVEt_OP 26 -#define SAVEt_NOHINTS 27 +#define SAVEt_HINTS 27 #define SSCHECK(need) if (savestack_ix + need > savestack_max) savestack_grow() #define SSPUSHINT(i) (savestack[savestack_ix++].any_i32 = (I32)(i)) @@ -89,21 +89,26 @@ save_destructor(SOFT_CAST(void(*)_((void*)))(FUNC_NAME_TO_PTR(f)), \ SOFT_CAST(void*)(p)) #endif -#define SAVESTACK_POS() STMT_START { \ - SSCHECK(2); \ - SSPUSHINT(stack_sp - stack_base); \ - SSPUSHINT(SAVEt_STACK_POS); \ - } STMT_END + +#define SAVESTACK_POS() \ + STMT_START { \ + SSCHECK(2); \ + SSPUSHINT(stack_sp - stack_base); \ + SSPUSHINT(SAVEt_STACK_POS); \ + } STMT_END + #define SAVEOP() save_op() -#define SAVEHINTS() STMT_START { \ - if (hints & HINT_LOCALIZE_HH) \ - save_hints(); \ - else { \ - SSCHECK(2); \ - SSPUSHINT(hints); \ - SSPUSHINT(SAVEt_NOHINTS); \ - } \ - } STMT_END + +#define SAVEHINTS() \ + STMT_START { \ + if (hints & HINT_LOCALIZE_HH) \ + save_hints(); \ + else { \ + SSCHECK(2); \ + SSPUSHINT(hints); \ + SSPUSHINT(SAVEt_HINTS); \ + } \ + } STMT_END /* A jmpenv packages the state required to perform a proper non-local jump. * Note that there is a start_env initialized when perl starts, and top_env diff --git a/t/lib/fields.t b/t/lib/fields.t new file mode 100755 index 0000000000..7fad5d78f2 --- /dev/null +++ b/t/lib/fields.t @@ -0,0 +1,110 @@ +#!./perl -w + +use strict; +use vars qw($DEBUG); + +my $w; + +BEGIN { + $SIG{__WARN__} = sub { + if ($_[0] =~ /^Hides field 'b1' in base class/) { + $w++; + return; + } + print $_[0]; + }; +} + +package B1; +use fields qw(b1 b2 b3); + +package B2; +use fields '_b1'; +use fields qw(b1 _b2 b2); + +sub new { bless [], shift } + +package D1; +use base 'B1'; +use fields qw(d1 d2 d3); + +package D2; +use base 'B1'; +use fields qw(_d1 _d2); +use fields qw(d1 d2); + +package D3; +use base 'B2'; +use fields qw(b1 d1 _b1 _d1); # hide b1 + +package D4; +use base 'D3'; +use fields qw(_d3 d3); + +package M; +sub m {} + +package D5; +use base qw(M B2); + +package Foo::Bar; +use base 'B1'; + +package Foo::Bar::Baz; +use base 'Foo::Bar'; +use fields qw(foo bar baz); + +package main; + +sub fstr +{ + my $h = shift; + my @tmp; + for my $k (sort {$h->{$a} <=> $h->{$b}} keys %$h) { + my $v = $h->{$k}; + push(@tmp, "$k:$v"); + } + my $str = join(",", @tmp); + print "$h => $str\n" if $DEBUG; + $str; +} + +my %expect = ( + B1 => "b1:1,b2:2,b3:3", + B2 => "_b1:1,b1:2,_b2:3,b2:4", + D1 => "b1:1,b2:2,b3:3,d1:4,d2:5,d3:6", + D2 => "b1:1,b2:2,b3:3,_d1:4,_d2:5,d1:6,d2:7", + D3 => "b2:4,b1:5,d1:6,_b1:7,_d1:8", + D4 => "b2:4,b1:5,d1:6,_d3:9,d3:10", + D5 => "b1:2,b2:4", + 'Foo::Bar::Baz' => 'b1:1,b2:2,b3:3,foo:4,bar:5,baz:6', +); + +print "1..", int(keys %expect)+3, "\n"; +my $testno = 0; +while (my($class, $exp) = each %expect) { + no strict 'refs'; + my $fstr = fstr(\%{$class."::FIELDS"}); + print "EXP: $exp\nGOT: $fstr\nnot " unless $fstr eq $exp; + print "ok ", ++$testno, "\n"; +} + +# Did we get the appropriate amount of warnings? +print "not " unless $w == 1; +print "ok ", ++$testno, "\n"; + +# A simple object creation and AVHV attribute access test +my B2 $obj1 = D3->new; +$obj1->{b1} = "B2"; +my D3 $obj2 = $obj1; +$obj2->{b1} = "D3"; + +print "not " unless $obj1->[2] eq "B2" && $obj1->[5] eq "D3"; +print "ok ", ++$testno, "\n"; + +# We should get compile time failures field name typos +eval q(my D3 $obj3 = $obj2; $obj3->{notthere} = ""); +print "not " unless $@ && $@ =~ /^No such field "notthere"/; +print "ok ", ++$testno, "\n"; + +#fields::_dump(); diff --git a/t/lib/trig.t b/t/lib/trig.t index c2bc2a8b5b..09147112c7 100755 --- a/t/lib/trig.t +++ b/t/lib/trig.t @@ -25,7 +25,7 @@ sub near ($$;$) { abs($_[0] - $_[1]) < (defined $_[2] ? $_[2] : $eps); } -print "1..7\n"; +print "1..20\n"; $x = 0.9; print 'not ' unless (near(tan($x), sin($x) / cos($x))); @@ -54,4 +54,103 @@ print "ok 6\n"; print 'not ' unless (near(rad2deg(pi), 180)); print "ok 7\n"; +use Math::Trig ':radial'; + +{ + my ($r,$t,$z) = cartesian_to_cylindrical(1,1,1); + + print 'not ' unless (near($r, sqrt(2))) and + (near($t, deg2rad(45))) and + (near($z, 1)); + print "ok 8\n"; + + ($x,$y,$z) = cylindrical_to_cartesian($r, $t, $z); + + print 'not ' unless (near($x, 1)) and + (near($y, 1)) and + (near($z, 1)); + print "ok 9\n"; + + ($r,$t,$z) = cartesian_to_cylindrical(1,1,0); + + print 'not ' unless (near($r, sqrt(2))) and + (near($t, deg2rad(45))) and + (near($z, 0)); + print "ok 10\n"; + + ($x,$y,$z) = cylindrical_to_cartesian($r, $t, $z); + + print 'not ' unless (near($x, 1)) and + (near($y, 1)) and + (near($z, 0)); + print "ok 11\n"; +} + +{ + my ($r,$t,$f) = cartesian_to_spherical(1,1,1); + + print 'not ' unless (near($r, sqrt(3))) and + (near($t, deg2rad(45))) and + (near($f, atan2(sqrt(2), 1))); + print "ok 12\n"; + + ($x,$y,$z) = spherical_to_cartesian($r, $t, $f); + + print 'not ' unless (near($x, 1)) and + (near($y, 1)) and + (near($z, 1)); + print "ok 13\n"; + + ($r,$t,$f) = cartesian_to_spherical(1,1,0); + + print 'not ' unless (near($r, sqrt(2))) and + (near($t, deg2rad(45))) and + (near($f, deg2rad(90))); + print "ok 14\n"; + + ($x,$y,$z) = spherical_to_cartesian($r, $t, $f); + + print 'not ' unless (near($x, 1)) and + (near($y, 1)) and + (near($z, 0)); + print "ok 15\n"; +} + +{ + my ($r,$t,$z) = cylindrical_to_spherical(spherical_to_cylindrical(1,1,1)); + + print 'not ' unless (near($r, 1)) and + (near($t, 1)) and + (near($z, 1)); + print "ok 16\n"; + + ($r,$t,$z) = spherical_to_cylindrical(cylindrical_to_spherical(1,1,1)); + + print 'not ' unless (near($r, 1)) and + (near($t, 1)) and + (near($z, 1)); + print "ok 17\n"; +} + +{ + use Math::Trig 'great_circle_distance'; + + print 'not ' + unless (near(great_circle_distance(0, 0, 0, pi/2), pi/2)); + print "ok 18\n"; + + print 'not ' + unless (near(great_circle_distance(0, 0, pi, pi), pi)); + print "ok 19\n"; + + # London to Tokyo. + my @L = (deg2rad(-0.5), deg2rad(90 - 51.3)); + my @T = (deg2rad(139.8),deg2rad(90 - 35.7)); + + my $km = great_circle_distance(@L, @T, 6378); + + print 'not ' unless (near($km, 9605.26637021388)); + print "ok 20\n"; +} + # eof diff --git a/t/op/array.t b/t/op/array.t index f307655ced..c0225a1107 100755 --- a/t/op/array.t +++ b/t/op/array.t @@ -1,8 +1,6 @@ #!./perl -# $RCSfile: array.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:37 $ - -print "1..40\n"; +print "1..37\n"; @ary = (1,2,3,4,5); if (join('',@ary) eq '12345') {print "ok 1\n";} else {print "not ok 1\n";} @@ -119,32 +117,6 @@ print $foo eq 'e' ? "ok 35\n" : "not ok 35\n"; $foo = ('a','b','c','d','e','f')[1]; print $foo eq 'b' ? "ok 36\n" : "not ok 36\n"; -# Test pseudo-hashes and %FIELDS. Real programs would "use fields..." -# but we assign to %FIELDS manually since the real module tests come later. - -BEGIN { - %Base::WithFields::FIELDS = (foo => 1, bar => 2, baz => 3, __MAX__ => 3); - %OtherBase::WithFields::FIELDS = (one => 1, two => 2, __MAX__ => 2); -} -{ - package Base::WithoutFields; -} -@ISA = qw(Base::WithoutFields Base::WithFields); -@k = sort keys %FIELDS; -print "not " unless "@k" eq "__MAX__ bar baz foo"; -print "ok 37\n"; -eval { - @ISA = 'OtherBase::WithFields'; -}; -print "not " unless $@ =~ /Inherited %FIELDS can't override existing %FIELDS/; -print "ok 38\n"; -undef %FIELDS; -eval { - @ISA = qw(Base::WithFields OtherBase::WithFields); -}; -print "not " unless $@ =~ /Can't multiply inherit %FIELDS/; -print "ok 39\n"; - @foo = ( 'foo', 'bar', 'burbl'); push(foo, 'blah'); -print $#foo == 3 ? "ok 40\n" : "not ok 40\n"; +print $#foo == 3 ? "ok 37\n" : "not ok 37\n"; @@ -4716,7 +4716,7 @@ STATIC SV * new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) { dSP; - HV *table = perl_get_hv("\10", FALSE); /* ^H */ + HV *table = GvHV(hintgv); /* ^H */ BINOP myop; SV *res; bool oldcatch = CATCH_GET; @@ -4757,7 +4757,7 @@ new_constant(char *s, STRLEN len, char *key, SV *sv, SV *pv, char *type) PUTBACK; pp_pushmark(ARGS); - EXTEND(sp, 3); + EXTEND(sp, 4); PUSHs(pv); PUSHs(sv); PUSHs(typesv); diff --git a/utils/perldoc.PL b/utils/perldoc.PL index 3805f6abe4..2b4ef6a0a9 100644 --- a/utils/perldoc.PL +++ b/utils/perldoc.PL @@ -123,8 +123,10 @@ getopts("mhtluvriFf:Xq:") || usage; usage if $opt_h || $opt_h; # avoid -w warning -$podidx = "$Config{'archlib'}/pod.idx"; -$podidx = "" if $opt_X || !-f "pod.idx" && !-r _ && -M _ > 7; +if( $opt_X ) { + $podidx = "$Config{'archlib'}/pod.idx"; + $podidx = "" unless -f $podidx && -r _ && -M _ <= 7; +} if ($opt_t + $opt_u + $opt_m + $opt_l > 1) { usage("only one of -t, -u, -m or -l") diff --git a/win32/config.bc b/win32/config.bc index 5ee5af64f7..447a999462 100644 --- a/win32/config.bc +++ b/win32/config.bc @@ -321,8 +321,8 @@ i_dld='undef' i_dlfcn='define' i_fcntl='define' i_float='define' -i_gdbm='define' -i_grp='define' +i_gdbm='undef' +i_grp='undef' i_limits='define' i_locale='define' i_malloc='define' diff --git a/win32/config.gc b/win32/config.gc index 73f8219819..0c5f5e039e 100644 --- a/win32/config.gc +++ b/win32/config.gc @@ -321,8 +321,8 @@ i_dld='undef' i_dlfcn='define' i_fcntl='define' i_float='define' -i_gdbm='define' -i_grp='define' +i_gdbm='undef' +i_grp='undef' i_limits='define' i_locale='define' i_malloc='define' diff --git a/win32/config.vc b/win32/config.vc index aefd0347c1..4740b50d08 100644 --- a/win32/config.vc +++ b/win32/config.vc @@ -321,8 +321,8 @@ i_dld='undef' i_dlfcn='define' i_fcntl='define' i_float='define' -i_gdbm='define' -i_grp='define' +i_gdbm='undef' +i_grp='undef' i_limits='define' i_locale='define' i_malloc='define' diff --git a/win32/include/dirent.h b/win32/include/dirent.h index 8cc7e11479..be363ce804 100644 --- a/win32/include/dirent.h +++ b/win32/include/dirent.h @@ -38,12 +38,12 @@ typedef struct _dir_struc struct direct dirstr; // Directory structure to return } DIR; -DIR *opendir(char *filename); -struct direct *readdir(DIR *dirp); -long telldir(DIR *dirp); -void seekdir(DIR *dirp,long loc); -void rewinddir(DIR *dirp); -int closedir(DIR *dirp); +DIR * win32_opendir(char *filename); +struct direct * win32_readdir(DIR *dirp); +long win32_telldir(DIR *dirp); +void win32_seekdir(DIR *dirp,long loc); +void win32_rewinddir(DIR *dirp); +int win32_closedir(DIR *dirp); #endif //_INC_DIRENT diff --git a/win32/makedef.pl b/win32/makedef.pl index d3a5196d7a..6592e468ed 100644 --- a/win32/makedef.pl +++ b/win32/makedef.pl @@ -583,6 +583,12 @@ win32_wait win32_waitpid win32_kill win32_str_os_error +win32_opendir +win32_readdir +win32_telldir +win32_seekdir +win32_rewinddir +win32_closedir Perl_win32_init Perl_init_os_extras Perl_getTHR diff --git a/win32/win32.c b/win32/win32.c index 68b6bb8962..03552debbf 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -637,7 +637,7 @@ do_exec(char *cmd) * return the pointer to the current file name. */ DIR * -opendir(char *filename) +win32_opendir(char *filename) { DIR *p; long len; @@ -715,7 +715,7 @@ opendir(char *filename) * string pointer to the nDllExport entry. */ struct direct * -readdir(DIR *dirp) +win32_readdir(DIR *dirp) { int len; static int dummy = 0; @@ -743,7 +743,7 @@ readdir(DIR *dirp) /* Telldir returns the current string pointer position */ long -telldir(DIR *dirp) +win32_telldir(DIR *dirp) { return (long) dirp->curr; } @@ -753,21 +753,21 @@ telldir(DIR *dirp) *(Saved by telldir). */ void -seekdir(DIR *dirp, long loc) +win32_seekdir(DIR *dirp, long loc) { dirp->curr = (char *)loc; } /* Rewinddir resets the string pointer to the start */ void -rewinddir(DIR *dirp) +win32_rewinddir(DIR *dirp) { dirp->curr = dirp->start; } /* free the memory allocated by opendir */ int -closedir(DIR *dirp) +win32_closedir(DIR *dirp) { Safefree(dirp->start); Safefree(dirp); diff --git a/win32/win32iop.h b/win32/win32iop.h index 6f4444eb3b..b22a1870a9 100644 --- a/win32/win32iop.h +++ b/win32/win32iop.h @@ -262,6 +262,13 @@ END_EXTERN_C #define waitpid win32_waitpid #define kill win32_kill +#define opendir win32_opendir +#define readdir win32_readdir +#define telldir win32_telldir +#define seekdir win32_seekdir +#define rewinddir win32_rewinddir +#define closedir win32_closedir + #ifdef HAVE_DES_FCRYPT #undef crypt #define crypt win32_crypt |