# pperl 0.6.23 *In development since 2026-10-11.* ## Modules - **MIME::Base64 uses vector instructions**: on x86-64, `encode_base64` and `decode_base64` work 12 or 24 bytes at a time where the processor has SSSE3 or AVX2. A large text in lines of equal length is now also decoded on several threads, as large data already was encoded; a text laid out any other way, or with stray characters in it, decodes on one thread as before. The results are unchanged. - **Digest::SHA uses the processor's SHA instructions**: the object interface (`Digest::SHA->new`, `add`, `addfile`) computes SHA-1 and SHA-256 with the processor's SHA instructions where it has them, as the functions such as `sha256_hex` already did. SHA-1 and SHA-512 are faster without them too. On x86-64 processors without the SHA instructions, SHA-1, SHA-224 and SHA-256 are faster in every form - functions, objects and HMAC. - **Encode converts single-byte encodings faster**: `encode` and `decode` for iso-8859-x, the cp125x code pages, koi8 and the other single-byte encodings no longer search a table for every character, and a string perl holds as bytes is encoded without first being converted to UTF-8. A large `encode` or `decode` is also spread over several threads. The results, the check modes and the error messages are unchanged. - **Cwd::getcwd is faster**: `getcwd` and the lexer no longer clear buffers of up to 4 KiB that are written before they are read. - **%Config entries that are not defined are undef**: `$Config{...}` returned the string "undef", which is true, for 232 keys such as `d_faststdio` and `usedl`, so `if ($Config{d_faststdio})` took the branch for something the build does not have. They are undef now, as in perl; `config_vars` and `config_sh` still print them as `'undef'`. - **Compress::Raw::Zlib needs no system zlib**: zlib is part of the binary now, as perl builds its own copy into the module, so `IO::Compress`, `Archive::Tar` and everything else on top of it work on a machine without `libz` and in the static build. Compression is 1.7 to 5.7 times as fast and decompression about twice as fast. A compressed stream is valid for every zlib but is not byte-for-byte the one perl writes, and `ZLIB_VERSION` reads `1.3.0-zlib-rs-0.6.8`. - **SDL_Quit with a Peta::WebGPU surface still alive no longer crashes**: a program that called `SDL_Quit` while a surface or an unpresented frame was still in scope aborted with "double free or corruption" in about one run in ten. `SDL_Quit` now releases their swap chains first; using such a surface or frame afterwards dies with a message saying the window system was shut down, and the device keeps working. - **Tie::Hash::Indexed is built in**: the ordered hash of CPAN's Tie::Hash::Indexed 0.08 loads without installing anything, as a tied hash and with its object interface, iterators and Storable support. Three sequences that crash perl with the original module work: `pop`, `shift` or `clear` in the middle of an `each` loop, and `NEXTKEY` before any `FIRSTKEY`. - **PDL: broadcast_define and the dataflow inspectors**: `broadcast_define` and `thread_define` now exist, with `broadcastover` and `broadcastover_n` under them. `trans_parent` and `trans_children` return `PDL::Trans` objects with their methods and vtable, so `PDL::Core::pdump`, `pdump_trans` and `pdumphash` work, as do `flags` and the `*_nophys` readers. Also new: `add_threading_magic`, `remove_threading_magic`, `broadcast3`, `tocomplex`, `hdr_copy`, `hcpy` and `nslice_if_pdl`. - **PDL: an ndarray's data is a Perl scalar**: the scalar that `get_dataref` returns is now the data itself for every ndarray above 32 bytes, so writing into it writes the ndarray, as in PDL under perl. That makes `new_around_datasv`, `new_around_pointer` and `set_data_by_file_map` (an ndarray over a memory-mapped file) available. `dump`, `bind` and `dowhenidle` are new too, and `datasv_refcount` of an ndarray without such a scalar dies. - **PDL: ldouble is the platform's long double**: `ldouble` and `cldouble` now hold the C compiler's `long double`, the 80-bit format on x86-64, as PDL under perl does; they were a 128-bit type with different results. A single `ldouble` value no longer reads as 0 in `print`, `sclr` and conversions. The complex functions are exact: `csqrt(-4)` is `2i`, not `1.22464679914735e-16+2i`. - **PDL: histograms, interpolate and the Image2D filters**: new are `histogram`, `whistogram`, their 2-D forms and `whist`; `wtstat`, `vcos`, `interpolate`, `diff2`, `diffcentred`, `partial`, `caverage` and `cavgover`; and in PDL::Image2D `conv2d`, `box2d`, `patch2d`, `patchbad2d`, `bilin2d`, `rescale2d` and `crop`. `hist` without bounds now chooses its bins from the data as PDL under perl does. `which` no longer counts bad values, `crossp` and `whichover` broadcast and keep the type, and `interpol` fills an ndarray given as fourth argument. - **PDL::ImageND**: `use PDL::ImageND` loads, with `convolveND`, `convolve`, `rebin`, `ninterpol`, `kernctr`, `circ_mean`, `circ_mean_p`, `contour_segments`, `contour_polylines`, `path_join`, `path_segs`, `combcoords`, `attract` and `repulse`. PDL::FFT imports `kernctr` from it again, as PDL under perl does. - **PDL: range and indexND as in PDL under perl**: `range` accepts an index with fewer dimensions than the source and a size per dimension, honours every boundary condition (`forbid`, `truncate`, `extend`, `periodic`, `mirror`, one for all dimensions or one each), keeps the type, and its result is linked to the source, so a write into it reaches the source. `rangeb` is new. `indexND` gains the same. - **PDL::Transform**: `use PDL::Transform` loads: coordinate transformations as objects (`t_linear`, `t_scale`, `t_offset`, `t_rot`, `t_lookup`, `t_fits`, `t_spherical`, `t_radial` and the others), their composition and inversion, `apply` and `invert`, and `map` and `unmap`, which resample an image through a transformation. PDL::Transform::Cartography adds the map projections (`t_mercator`, `t_orthographic`, `t_gnomonic` and the others), `graticule` and `clean_lines`; `earth_coast` and `earth_image` need their data files from an installed PDL. - **PDL: headers belong to the ndarray**: an ndarray's header (`sethdr`, `gethdr`, `hdr`) is released with the ndarray; it used to stay in memory, and a later ndarray could come up with a stranger's header. With `hdrcpy` set, every operation now gives its result a deep copy of the header and the flag, where only slices did. `sethdr` refuses anything but a hash reference or undef. - **PDL: accessors take their argument as PDL under perl does**: `nelem`, `dims`, `ndims`, `isnull`, `get_datatype`, `nbytes`, `sever`, `badflag` and the like accept a number or an array reference as a one-off ndarray and die on the class name, where they returned 0 or nothing. After an explicit `$pdl->DESTROY` any use of `$pdl` dies with "Fatal error: ndarray address is NULL". `dimincs` of a view gives the view's increments, and `readonly` refuses a null ndarray. - **PDL: a negative zero prints as -0 in a matrix**: a matrix whose elements go through `$PDL::doubleformat` or `$PDL::floatformat` now formats each number itself, so `-0` keeps its sign. `$VERSION` is `2.096` in PDL::Core and unset in PDL::Ufunc, PDL::Slices and the other generated modules, as in PDL; they all said `2.103`. - **PDL: set_debugging prints the trace**: with `PDL::Core::set_debugging(1)` PDL prints what it does, step by step, to standard output, as PDL under perl does; it printed nothing. - **PDL: badflag spreads as in PDL under perl**: setting or clearing `badflag` now reaches the ndarrays it does in PDL: the parents of a view and their flowing children, not the other views of the same parent. Clearing it on a parent used to leave a view of a view set, and setting it never reached flowing children. - **PDL 2.106**: the embedded PDL is 2.106, up from 2.104. `hclip` and `lclip` work in place, PDL::Constants has `DEG2RAD` and `RAD2DEG`, and `avgover`, `minover`, `maxover` and the other "over" synonyms are methods only, no longer imported by `use PDL`. A condition on an ndarray of several elements dies with the full message of PDL, its `PDL::overload_bool` line included. The two functions new in 2.105, `isnan` and `casinh`, are not there yet. - **Peta::Shell::Session evaluates Perl line by line**: a new built-in module that runs pieces of Perl one after another and keeps what each leaves behind: `my` variables, pragmas, the current package. It says when a text is unfinished and returns the value of the last statement. It is the evaluator of ipps, the interactive mode. ## Command line - **pperl -v describes the runtime in one line**: the banner now says "It features JIT, auto-parallelization and GPU acceleration." - **--shell starts ipps, the interactive mode**: `pperl --shell`, or pperl run under the name `ipps`, gives a prompt that runs Perl, prints the value of the last statement and keeps variables, subs and pragmas from line to line. It has line editing, history, a second prompt for unfinished input and a start file, `~/.pperl/ipps/rc.pl`; without a terminal it reads lines from standard input. A bare `pperl` still reads a program from standard input as perl does. The reserved `--interactive` switch is gone. - **ipps has commands, settings and macros**: a line that starts with a colon and a word is a command: `:help` lists them. `:vars` shows the session's variables, `:time` and `:jit` run a line and report on it, `:dump` shows a value whole, `:source` a sub's code, `:which` where a module comes from; `:install`, `:load`, `:save`, `:set`, `:history`, `:reset` and `:quit` do what their names say. In `~/.pperl/ipps/rc.pl`, `Peta::Shell->macro`, `->command` and `->set` define words that expand to Perl, commands of your own and settings. - **ipps runs a command of your shell after !**: a line that starts with `!` and a space is handed to your shell and runs on the terminal, as in `! ls -l *.pl`. It runs under `$SHELL -c`; the new `shell` setting changes that, for example to `bash -ic` for bash's aliases. Without the space, `!` is Perl's negation as before. - **ipps completes with Tab**: the Tab key completes the word in front of the cursor: a variable of the session, a key of one of its hashes (`$data->{list}[0]{` too), a method of an object or class, a sub, a module after `use`, a file name inside a string, a command, and a file name where none of those fits. A second Tab lists the candidates when there are several, and the prompt and the line are drawn again below the list; that holds for every program that completes through Term::ReadLine. - **ipps shows a value as it is written in Perl**: a number bare, a string in quotes, `undef`, `true` and `false`, an array or hash as its structure, an object with its class in front. A string gets the quotes that need the fewest escapes: `'$5 each'`, `q{it's}`, `"a\tb"`. Large values are cut with a note of what was left out, and the layout follows the width of the terminal. The value last shown is in `$ans`, and `@ans` when there were several. - **--cpan runs the built-in CPAN client**: `pperl --cpan` installs with the CPAN client that is part of the binary and no longer needs `cpanm` on the machine, so it works where no perl5 is installed. The options after `--cpan` are those of the `cpan` command, `-T` in place of `--notest`. A git repository, a directory or an archive file can still be named in place of a module. - **--cpan installs only what loads after a failed XS build**: when a distribution's compile fails, `--cpan` installs its Perl files as before, but a module that loads the compiled part is now loaded once first and left out, by name, if it cannot load without it. A module that is only the front of its compiled part used to be installed and then reported as up to date on the next run. A directory named on the command line is covered too. - **Built-in Perl modules count as installed**: `--cpan` now also treats the Perl modules the binary carries, such as `Test::More`, as installed, at their versions. It used to read a host perl's copies of them, or try to install them where there was none. Asked for a module that is built in, `--cpan` says so and builds nothing, also when CPAN has a newer release. - **--native-manifest is gone**: `--cpan` no longer writes pperl's module inventory to disk, and the `--native-manifest=DIR` option that wrote it for other installers is removed. The installer asks `Config::lib_file` instead. - **Modules for other operating systems are no longer built in**: `ExtUtils::MakeMaker`'s and `ExtUtils::CBuilder`'s files for VMS, Windows, OS/2, AIX, macOS and other systems, 26 in all, and the `vmsish` pragma are no longer part of the binary. The `File::Spec` modules for other systems stay. - **A host perl's core directories are no longer searched**: `@INC` no longer lists the core library directories of a perl5 installed on the machine, because every module in them is built into pperl and was never loaded from there. The site and vendor directories are searched as before, now under whichever perl version the host has. - **Makefile.PL builds the Perl part only**: `ExtUtils::MakeMaker` under pperl no longer tries to compile a distribution's C or XS, so a `Makefile.PL` needs no compiler, no perl header files and no perl5 on the machine. A module that cannot load without its compiled part is left out and named, the rest of the distribution is built, and its own tests decide whether it is installed. The "different ideas about the architecture" notice is gone, and `$Config{privlibexp}` and `$Config{archlibexp}` name the built-in library. - **Config::lib_files lists the built-in library**: the new function `Config::lib_files()` returns the names of all library files inside the pperl binary, in the form `require` takes (`File/Temp.pm`). - **Config::jit_counts says what the JIT has compiled**: the new function `Config::jit_counts()` returns two numbers, the loops the JIT has compiled to machine code since the program started and the loops it has seen. It returns the empty list when the JIT is off. - **Config::lib_file says where a library file is**: the new function `Config::lib_file("Foo/Bar.pm")` returns the path under which pperl sees that file, a built-in one first, or `undef`. The path can be opened; a built-in module without Perl source reads as its package and version. `ExtUtils::MakeMaker`, `Module::Metadata` and `CPAN` ask it, so a `Makefile.PL` no longer reports a built-in prerequisite as not found. ## Documentation - **A tutorial for ipps**: a new tutorial, "ipps, the interactive mode", walks through a first session, the commands, the start file with its settings and macros, and the places where a line at the prompt behaves differently from a line in a file. - **Changelog translations**: the changelog pages of versions 0.5.6 to 0.6.22 are translated into the 41 languages of the documentation. Entries of earlier versions name the Benchmarks Game programs and group the digits of large numbers the same way on every page, and two entries of 0.6.22 that were cut in two on the page read as one again. - **Reference sidebar starts collapsed**: the section navigation of the Reference shows one line per namespace when you enter it, and opens only the branch of the page you are reading. It used to open every namespace at once, which made the sidebar several hundred lines long.