Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re^2: Can I access and use UV types from perl?

by Don Coyote (Hermit)
on Nov 17, 2019 at 18:29 UTC ( [id://11108824]=note: print w/replies, xml ) Need Help??


in reply to Re: Can I access and use UV types from perl?
in thread Can I access and use UV types from perl?

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.

Replies are listed 'Best First'.
Re^3: Can I access and use UV types from perl?
by haukex (Archbishop) on Nov 17, 2019 at 19:31 UTC

    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.

      Thank you haukex this is a good explanation.

      In a sense am I being a little bit confused around what Devel:Peek is telling me, bearing in mind I am using a 5.14 version.

      $n = unpack "C", pack "B", 128; &print_val; $n += $n; &print_val; #output #SV = IV(0xe28558) at 0xe2855c # REFCNT = 1 # FLAGS = (PADMY,IOK,pIOK) # IV = 128 # ### #SV = IV(0xe28558) at 0xe2855c # REFCNT = 1 # FLAGS = (PADMY,IOK,pIOK) # IV = 256 # ###

      These are actually UV values then? but Perl is storing them as IV's. and the sum at the microprocessor level, adding 128 to itself, is carrying out a binary addition of a natural number.

      I have only just found out about two's complement a couple of weeks ago, and I'm not sure where I stand on that just yet.

        In a sense am I being a little bit confused around what Devel:Peek is telling me

        If you want to dive into that rabbit hole, see perlguts and the rest of the internals documentation, although be warned, that's not light reading.

        These are actually UV values then? but Perl is storing them as IV's.

        Those values will fit fine into a signed integer, so as per dave_the_m's explanation, Perl has no need to upgrade them to a UV. It might be interesting to note that Perl can store pretty big integer values. As per ikegami's post here:

        1. Largest integer value that can be stored as a signed integer: ~0 >> 1 (on my machine: 9,223,372,036,854,775,807), and the smallest: -(~0 >> 1)-1
        2. Largest integer value that can be stored as an unsigned integer: ~0 (on my machine: 18,446,744,073,709,551,615)
        3. All integer values from 0 to this number can be stored without loss as a floating point number: $Config{nv_overflows_integers_at} (on my machine: 9,007,199,254,740,992)
        two's complement

        One of the things that really helped it click for me back then was this graphic, along with looking at different 2's complement mathematical operations (Update 2: as I showed in my reply below):

        0 -1 0000 1 1111 0001 -2 2 1110 0010 -3 3 1101 0011 -4 4 1100 0100 -5 5 1011 0101 -6 6 1010 0110 -7 7 1001 -8 0111 1000

        Update: In the graphic I accidentally wrote "8" when it should have been "-8", sorry, fixed.

Re^3: Can I access and use UV types from perl?
by syphilis (Archbishop) on Nov 17, 2019 at 22:53 UTC
    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

      The negative numbers come out as UV's but the positive numbers come out as IV's

      for( -1 .. 1) { print s2u($_), "\n"; } sub s2u { Dump sprintf("%u", $_[0]) + 0; } =head1 output SV = IV(0x732998) at 0x73299c REFCNT = 1 FLAGS = (PADTMP,IOK,pIOK,IsUV) UV = 4294967295 SV = IV(0x732998) at 0x73299c REFCNT = 1 FLAGS = (PADTMP,IOK,pIOK) IV = 0 SV = IV(0x732998) at 0x73299c REFCNT = 1 FLAGS = (PADTMP,IOK,pIOK) IV = 1 =cut
        The negative numbers come out as UV's but the positive numbers come out as IV's

        Yes, and that's why I was careful to state that it converted "signed integer values" to "unsigned integer values" (as opposed to converting IVs to UVs).

        Does it matter that the IsUV flag is not set for values less than or equal to MAX_INT (which is 9223372036854775807 on my machine, and 4294967295 on yours)?
        If so then you face a significant problem - AFAIK there's no way to set the IsUV flag for an integer whose value <= MAX_INT.
        And perl won't call it a "UV" unless the IsUV flag is set.
        Essentially, the IsUV flag (and also the term "UV") indicates that it's a positive integer whose value is greater than MAX_INT.

        You might be able to turn the IsUV flag on for all positive IVs via XS or Inline::C.
        I don't know if it's possible - if it is possible then I don't know what it would break, or even if the IsUV flag could be made to stick when the value <= MAX_INT.

        Cheers,
        Rob

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-03-28 20:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found