XML

kent logo

CO631 Anonymous Questions and Answers Keyword Index

This page provides a keyword index to questions and answers. Clicking on a keyword will take you to a page containing all questions and answers for that keyword, grouped by year.

To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.

Keyword reference for type-cast

2004

Question 101 (2004):

Do we need to use occam that is going to work on raptor or can we make use of the additions in the KRoC/Linux version. For example I'm considering using the STEP stride part for the replicator.

Next when using replicators, why can't I pass "i" into the "cursor.x.y()" PROC in this code ?

    PAR i = 8 FOR 5 STEP 2
      SEQ
        cursor.x.y(23,i,out)
        -- print stuff

Where "i" is the line number. The error is a type mismatch for parameter 2 in "cursor.x.y()". Surely "i" is an integer and should be accepted ?

Any help appreciated...

Answer 101:

For KRoC/Linux extensions (rather, occam-pi extensions), yes, using those is fine. We'll most likely be testing your code on such a machine.

The reason you can't pass "i" as a parameter is because "cursor.x.y" takes "VAL BYTE" parameters (not "VAL INT"). The solution for such things is to cast the parameter to the appropriate type:

    cursor.x.y (23, BYTE i, out)

Given the code you've got above, it should generate another error also (related to parallel usage), but that should be slightly more obvious.

Keywords: q7 , type-cast

2003

Question 111 (2003):

I found a problem doing a past exam question, while trying to cast an INT into a REAL32:

    INT sum:
    SEQ
      ...
      out ! values[index]; (REAL32 sum) / 10

but the compiler complains:

    "Type of operand invalid for exact type conversion REAL32"

Answer 111:

The designers of occam were very precise mathematicians, amongst other things. When you cast an INT into a REAL32, you don't expect precision problems - e.g. 42 should become 42.0 precisely (and it does).

However, large INTs do not convert exactly into REAL32s ... which only use (around) 24 bits to hold the mantissa (the actual number) and the rest to hold the exponent amd sign bits. But INTs use 31 bits to hold the actual number and 1 for the sign. Now, 31 into 24 don't go! So, only the first 24 bits go over when casting and the rest are implied zeroes (how many is defined by the exponent bits). The least precision bit of those 24 bits has to be decided. That decision requires you to specify whether that's to be done by rounding (to the nearest whole 24 bits value) or truncating towards zero. In occam, you must make that specification ... so your line should have been either:

    out ! values[index]; (REAL32 ROUND sum) / 10.0

or:

    out ! values[index]; (REAL32 TRUNC sum) / 10.0

depending on what you want. I don't know any other language (?) that is as fussy as this but the care is justified. Java/C will cast an int to a float without batting an eyelid ... does anyone know which way it decides that final bit when the number is too large ... I bet different C compilers will generate code that does different things ... may even be architecture dependent, so that the same compiler does different things on different architectures. May also be true for Java.

Of course, if your INT value is between ``-2**23'' and ``(2**23 - 1)'', then no decision about rounding-v-truncating is needed. But the occam cast is still `REAL32 ROUND' or `REAL32 TRUNC', which both give the same (and expected) result in these cases.

NB: the `10.0' divisor corrected above ... because occam only allows division of one type by the same type! And `10' is an INT and occam does also not allow automatic casting ... :-) ... you must say it to get it!!

PS: when casting the other way - from a REAL32 to an INT, we also need to specify what happens to the final bit. This is for a different reason though ... nothing to do with large numbers, but to do with fractional numbers. For example, should 42.7 become 42 or 43? Either may be what is required. What you get is what you say:

INT i, j, k: REAL32 x: SEQ x := 42.7 i := INT ROUND x -- i gets 43 j := INT TRUNC x -- j gets 42 k := INT x -- will not compile! (You must say!!)

See also the code on raptor in:

    /usr/local/courses/co516/examples/casting.occ

Keywords: type-cast


Question 101 (2003):

I'm using cursor.x.y to make my interface but I've run into a problem. cursor.x.y takes two BYTEs and my program involves general formulas that take the fork/philosopher number and use it to calculate the co-ordianates of where the cursor needs to be. Is there any way of casting an INT straight into a BYTE of the same number? For instance, of the `x co-ord' needs to be ``(2 * philosopher number) + 2'', how can I get that from being an INT to being a BYTE I can use in `cursor.x.y' ?

Answer 101:

Lookup type-cast in the keyword index. I've also set up cast as a synonym in this index.

Keywords: type-cast , cast


Question 89 (2003):

Hi, I am having trouble with the `cursor.x.y' proc.

It will not accept the second parameter:

    INT id:
    ...
      [snip code]
      cursor.x.y (10, id, scr)

I thought an INT could be used as long as it isnt less than 0 or greater 255

Answer 89:

Such an INT can be used, but you need to cast it into a BYTE first. This can be done with: ``(BYTE id)''. If `id' is out of range for a BYTE, a run-time error occurs.

See also the answers to Question 74 (2000) and Question 73 (2000).

Keywords: type-cast , cast

2002

Question 10 (2002):

For q2, the keyboard channel takes a BYTE. How do I cast a BYTE to an INT?

Answer 10:

q2 does not require you to touch the keyboard channel - do you mean the screen one?

You can cast a BYTE to an INT ... but you don't want to do that for this question. You need to be able to output an (ASCII) character representation of an INT to the screen channel - but that's OK since that will be a sequence of BYTEs (which are the only things you can output to the screen). And that's done for you by the tabulate.int process, given to you in your q2.occ starter file.

If you really want to know about casting in occam, see Question 7 (2000).

Keywords: type-cast , cast

2000

Question 74 (2000):

Is there anyway to cast INTs to BYTEs?

Answer 74:

Yes. See the answers to Question 7 (2000), Question 66 (2000) and Question 73 (2000) - for example.

Keywords: type-cast , cast

Referrers: Question 89 (2003)


Question 73 (2000):

I have the following code:

    VAL INT i.mod.n IS i\n:
    in[i.mod.n] ? CASE
      thinking
        SEQ
          cursor.x.y (1, (i.mod.n * 4) + 5, screen)

which generates an error saying that the operator * has operand of different types. Is 4 not an INT as I assumed it would be? Or is it because i.mod.n is a VAL INT and 4 is a plain INT?

If it is the latter, surely not allowing a VAL INT to be muliplied together by an INT is being rather pedantic - seeing as they are obviously both INTs.

Anyway, as to a solution, is there any reason why i.mod.n is a VAL INT rather than just a plain INT which would allow me to mutiply with it without having to define all my other values as VAL INTs?

Answer 73:

The first two parameters for cursor.x.y are screen coordinates and they are of type BYTE - so BYTEs must be supplied.

The compiler looks for a BYTE as the first parameter and finds a 1 - that'll do! When it looks at the second argument, it finds an expression - an addition of two operands. The result has to be a BYTE which implies that both those operands must be BYTEs. The right operand is 5 - which is fine. The left operand is another expression - a multiplication of two operands. That result must be a BYTE and so, therefore, must be its two operands. Now, the right operand is 4 - which is fine. But the left operand is i.mod.n, which is an INT - not a BYTE. Error!

occam has a very simple rule about binary operators in expressions: both operands must have the same type and the same precision and the result has that same type and precision. There is no automatic casting between types - all casts, if needed, must be explicitly programmed. What-you-see-is-what-you-get.

Your other points about VAL are not relevant. VALs have no impact on types. A named VAL INT has INT type and may be freely added/multiplied/etc. with other INTs (whether VAL INTs or variable INTs). We want i.mod.n to ba a VAL because we don't ever need to change it - declaring it as a VAL will get the compiler to reject any code we might mistakenly write that tries to change its value.

To correct your code, you can't just declare i.mod.n to be a VAL BYTE. This is because it is used to index an array and array indices are always INTs. Instead, cast it at the point in your code where it needs to be a BYTE:

          cursor.x.y (1, ((BYTE i.mod.n) * 4) + 5, screen)

Of course, you have to be sure that evaluation of the above expression will always remain within the legal bounds of a BYTE (which are 0 through 255 inclusive). Hopefully, this will be the case.

Note: the above expression will cause the arithmetic to be performed using BYTE arithmetic. The following code causes INT arithmetic to be used (which on a SPARC or Pentium etc. will be more efficient - although that would not be not the case if we were compiling directly into silicon) and only casts the result into the needed BYTE:

          cursor.x.y (1, BYTE ((i.mod.n * 4) + 5), screen)

Keywords: type-mismatch , type-cast , cast

Referrers: Question 89 (2003) , Question 74 (2000)


Question 66 (2000):

For question 7, I am trying to draw a boarder for the dining philosophers room. I can do it with lots of cursor.x.y and out.string procedures but this seems time consuming. I thought of doing it in a replicated PAR or replicated SEQ and I wrote this code:

  #INCLUDE "consts.inc"
  #USE "course.lib"

  PROC a (CHAN OF BYTE out)
    PAR i = 1 FOR 26
      SEQ
        cursor.x.y (4, i, out)
        out.string ("#", 0, out)
  :

  PROC test (CHAN OF BYTE keyboard, screen, error)
    PAR
      a (screen)
      ...  other things
  :

But when I compile it, it says there is a type mismatch in parameter 2 of cursor.x.y. This is the y coordinate that I am changing so that the character gets printed on the line below the first one to create a column like this:

      #
      #
      #
      #
      #
      #

Why does the compiler not like the second parameter of the cursor.x.y proceedure? Doesen't it just need to be a number?

Answer 66:

The second parameter of cursor.x.y needs to be a BYTE. Replicator control variables (e.g. your i) are INTs. You need to cast it into a BYTE:

        cursor.x.y (4, BYTE i, out)

See the answer to Question 7 (2000) for information on casting between occam types.

Your PAR replicator also won't work because it implies parallel outputs to the out channel - illegal! So it has to be a SEQ replicator. In any case, unless the occam kernel supports, and is running on a multiprocessor machine, the SEQ replicator for code like this will be faster than a PAR (which will have to startup and shutdown 25 software processes).

Your code would also be slightly snappier with:

  PROC a (CHAN OF BYTE out)
    SEQ
      cursor.x.y (4, 1, out)
      SEQ i = 1 FOR 26            -- the "2" could be anything though
        SEQ
          out ! '#'               -- don't need out.string for a single char
          cursor.down (1, out)
          cursor.left (1, out)
      out ! FLUSH

Keywords: q7 , type-mismatch , type-cast , cast , cursor

Referrers: Question 21 (2001) , Question 74 (2000)


Question 7 (2000):

How can I cast an INT to a BYTE ?

Answer 7:

If x is an INT variable whose value is between 0 and 255 inclusive, then (BYTE x) is its BYTE equivalent. If x were outside the BYTE range, then (BYTE x) would give a run-time error.

In general, to cast from one primitive type to another, use the target type name as a prefix unary operator. For casting between certain types, rounding considerations become necessary (as the precision available in the target type is less than that of the source) and we have to state how the least significant bit is to be resolved (either by ROUNDing or TRUNCation). The details are low-level but, for some applications, crucial to get right. If you want to know more, look at the file:

  examples/casting.occ

which you should already have copied from the co516 course directory.

A key point to remember is that there is no automatic casting between data types in occam - what-you-see-is-what-you-get!

Keywords: type-cast , cast

Referrers: Question 87 (2003) , Question 10 (2002) , Question 8 (2000) , Question 66 (2000) , Question 74 (2000)

Valid CSS!

Valid XHTML 1.0!

Last modified Mon May 15 17:39:48 2006
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.