Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Can I access and use UV types from perl?

by Don Coyote (Hermit)
on Nov 17, 2019 at 16:35 UTC ( [id://11108820]=perlquestion: print w/replies, xml ) Need Help??

Don Coyote has asked for the wisdom of the Perl Monks concerning the following question:

I'd like to access and use unsigned int at the level of Perl. Ideally I would not need to employ XS or inline C. Put simply I'd like to add 1 to 1, without 1 being converted into a signed integer first.

Using Perl 5 I seem to be able to coerce a scalar into storing a UV type, but initial attempts to use it in any form appear to be subject to up/downgrading.

If I use an approach such as bounding a tied scalar as exampled in Intermediate Perl (O'Reilly), I feel this may be suitable for prototyping methodology of usage, but falls short of actually using the underlying unsigned int type.

This quickly boils down to a question about fundamentals, and I am not so concerned about there being any straight forward yes or no answer, (though a yes would be great). As I sense the very nature of Perl 5's dualvar probably does not allow this. But will I find that Perl 6 has the same issue, or would this be something that Perl 6 would happily enable for me?

Maybe there is some way I can do this but where I do need to delve into XS or maybe overloading? I have been hacking at this using the MvT (Monkey vs Typewriter) method a lot and have included my latest effort where I get Devel::Peek to display a UV type.

I have also been doing various MvT with vec,pack,printf functions My overall sense is that any outcome from this could serve as the basis for some very useful Perl/CompSci tutorials.

#!perl use strict; use warnings; use vars q'$n'; use Devel::Peek; #my $n = 4; #&print_val; sub print_val{ # my $n = shift; my $n = shift() || $n; print ' ', Dump $n; print "###\n"; } $n = ~( 1 ); $n <<= 30; #&print_val($n); print "left shift 30\n"; &print_val; $n = ~( 1 ); $n <<= 31; print "left shift 31\n"; &print_val; #=head1 powers #my $n = ~( (2**32) -( (2**32)-1 # -( # (2**30) + ((2**29)-1) # ) ) ); print "base 2 combos\n"; &print_val; #=cut $n+=$n; print "self addition assignment\n"; &print_val; #=cut

I have asked as SoPW, as there may be some simple approach that I am just missing.

updated couple of spelling errors, nothing significant.

Replies are listed 'Best First'.
Re: Can I access and use UV types from perl?
by dave_the_m (Monsignor) on Nov 17, 2019 at 18:07 UTC
    When a value becomes too big to store as a signed integer, perl automatically upgrades it to an unsigned integer (technically it sets the SVf_IVisUV flag on the SV). If the value becomes too large even for that, then the SV is upgraded to an NV. This is all automatic and you shouldn't have to do anything yourself (unless you're using an ancient version of perl).

    Try running

    perl -MDevel::Peek -e'$x=(1<<60)-1; for (1..6) { Dump $x; $x = $x *2 + + 1}'
    If you want something more than this, you'll have to explain your need better.

    Dave.

      dave_the_m I see the lowercase f there making me think floats, yikes. oh, its a flag :smile.

      The automagic of Perl values is a great thing, which I value immensely. Please see Re^2: Can I access and use UV types from perl? for a substantial waffle regarding my deeper motives for this expiditionary embarkation.

      On one level I want to be able to say I am adding natural numbers together and be speaking truthfully, rather than saying that, but actually what is happening is that I am adding a subset of integers together.

      Looking at the output. There does seem to be some kind of interplay between the size of the storage unit and the kind of number that Perl assumes the user is wanting to use. That is interesting.

        On one level I want to be able to say I am adding natural numbers together and be speaking truthfully, rather than saying that, but actually what is happening is that I am adding a subset of integers together.

        Then maybe use bignum or bigrat, at a significant performance cost.

Re: Can I access and use UV types from perl?
by haukex (Archbishop) on Nov 17, 2019 at 17:17 UTC

    Although it's not exactly what you're looking for, have a look at use integer.

    I'd like to access and use unsigned int at the level of Perl. ... This quickly boils down to a question about fundamentals, and I am not so concerned about there being any straight forward yes or no answer

    I think the main question is: why? Because this sounds like it could likely be an XY Problem. Then maybe we can suggest some more appropriate solutions than XS, Inline::C, or Math::BigInt.

      use_integer literally turns all the values into IV's. For me that is exactly a counterexample of what I want to be able to do.

      To answer the question why, is certainly something I hope I can explain clearly.

      Variously I consider can I do X or Y and how or why not. In a sense I'd just like to ask my computer to do what I would think many people would agree is or at least should be considered the most straight forward thing that a computer can do, add 1 to 1.

      At some point though it seems like somewhere somebody decided that, well, before we can do that we have to convert this thing we call 1 into some more complicated thing called an integer with a respective value of 1, that can then be added to itself to produce the answer to this question.

      To this I say, cool now we're doing computing, but, can we just add 1 to 1 first, without turning into one of those.. uhm integer thingys?

      From an educational aspect, it is a bit like saying, ok I get we are all using signed ints as the basis of our computing because it leads to a lot of efficiencies and optimisations, but where are those intermediate steps we took to go from using a byte as a 7 bit bit field to using it as an 128 decimal mapping to a non-symmetric range around zero.

      Historically there are a lot of transformations in how character sets have evolved, from pre-Ascii through to UTF, which we are currently trying to get our heads around, and the story is fascinating and evolving.

      Numbers themselves are going through similar transformations, but it seems that about fifty plus years ago somebody said right its all integers for computing and thats been the final word (lol) so to speak for a long time.

      Perhaps there needs to be some kind of exclusive transformation format for number themselves, also. Not just a character representation format. Maybe there already is and as I mentioned in my OP I am just missing it. However, either way, that I have been wearing down keyboards for such a time without being able to approach this simply, probably means there is some kind of need to be able to do this out there.

      There are a couple (and more) quirks out there. One relating to Perl is in the difference between return values. Perl returns undef, zero or > zero, whereas C can return negative one. Does this mean that Perl returns unsigned int values, whereas C returns signed int values?

      Another quirk is the ever hilarious signed char, how has that got in there? to the casual observer this is an extraordinary concept, but it obviously relates to how numbers have evolved within computing to be used as mappings for language. In the Perl documentation there is a hint, think of Perl IO as octects or characters. This helps, but I do wonder what this strange signed char thingy is. Are they there so my papers can be marked in the work to do range?

      So I'd like to approach what we do now, naively, as an exercise in understanding what is going on and how we got here.

        Sorry, but I still don't understand. See XY Problem - what I was asking is what practical requirement you have such that you are required to use unsigned ints.

        use_integer literally turns all the values into IV's.

        No, see integer: It changes the way the operators work.

        At some point though it seems like somewhere somebody decided that, well, before we can do that we have to convert this thing we call 1 into some more complicated thing called an integer with a respective value of 1, that can then be added to itself to produce the answer to this question. To this I say, cool now we're doing computing, but, can we just add 1 to 1 first, without turning into one of those.. uhm integer thingys?

        If by "integer thingys" you mean Perl's data types, then yes, Perl does abstract out the underlying representation of the values. Perl is a higher-level language, and there is only a limited amount of sense in trying to work with Perl on a lower level - if there is a requirement to work with specific data types (or you just want to learn more about the underlying data types), then it's usually best to use a language that works more closely to the machine level, such as C. Perl abstracting these things removes a lot of the complexity that can arise in languages such as C, such as having to cast between different data types manually, at the cost of some performance and memory usage relative to C. But the lower complexity also means less chance to introduce bugs due to incorrect typecasts (not to mention all the complexities that are avoided by having dynamic string and array sizing, references instead of pointers, and automatic memory management).

        One relating to Perl is in the difference between return values. Perl returns undef, zero or > zero, whereas C can return negative one. Does this mean that Perl returns unsigned int values, whereas C returns signed int values?

        Many C functions do return ints, i.e. signed ints. However, as I said above, Perl functions return Perl's own variable types, and there are also Perl functions that mirror the underlying C API and return negative values.

        From an educational aspect, it is a bit like saying, ok I get we are all using signed ints as the basis of our computing because it leads to a lot of efficiencies and optimisations, but where are those intermediate steps we took to go from using a byte as a 7 bit bit field to using it as an 128 decimal mapping to a non-symmetric range around zero.

        Modern processors can handle unsigned and signed integers of varying widths (64 bits on modern architectures) natively, there are no "intermediate steps" there. If your goal here is to learn more about the underlying operations, it might be best if you take some time to look at C. You might also be interested in Two's complement math - the great thing about it is that there isn't really a "mapping" necessary to do many of the operations.

        This helps, but I do wonder what this strange signed char thingy is.

        It's (pretty much always) an octet that stores the values -128 to 127 instead of 0 to 255 (unsigned char).

        $ perl -e 'print"unsigned signed\n";printf"%-3d %08b %4d\n",$_,$_,un +pack"c",pack"C",$_ for 0..255' unsigned signed 0 00000000 0 1 00000001 1 2 00000010 2 3 00000011 3 ... 125 01111101 125 126 01111110 126 127 01111111 127 128 10000000 -128 129 10000001 -127 130 10000010 -126 ... 253 11111101 -3 254 11111110 -2 255 11111111 -1

        It's the same bits, just different interpretations. The difference of how which bits are treated happens at the at the lowest level, in the assembly instructions provided to the microprocessor. In C, when you say that a variable is a signed int or an unsigned int, that will tell the C compiler which assembly instructions to emit when doing operations with those variables. Perl's runtime abstracts that out even more, so that you don't have to worry about signed vs. unsigned or even int vs. float.

        use_integer literally turns all the values into IV's. For me that is exactly a counterexample of what I want to be able to do.

        If you want to turn all signed integer values into unsigned integer values:
        use strict; use warnings; for(-3 .. 3) { print s2u($_), "\n"; } sub s2u { sprintf("%u", $_[0]) + 0; } __END__ OUTPUT: 18446744073709551613 18446744073709551614 18446744073709551615 0 1 2 3


        Cheers,
        Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11108820]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (6)
As of 2024-03-29 14:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found