CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 22

Thread: 24 bit integer

  1. #1
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835

    24 bit integer

    Anybody got any ideas about how I could implement 24 bit integer types? For example, with some compilers I've seen things like:-

    typedef long long int Int64;
    typedef unsigned long long int UInt64;

    which are used for 64 bit types, but I want 24 bit types (3 bytes). I'd want to be able to do normal maths with them (plus, minus, multiply, divide etc) and assign values such as:-

    UInt32 x = 24117248; // 0x1700000 (this overflows a 24 bit Uint)
    UInt24 y = x; // result would equal 7340032 (0x700000) which is within range.

    [Edit]
    Ideally, they should also be capable of being cast to any of the other integer types - e.g.

    Code:
    Int32 SomeFuncThatRequiresA16BitInt ( Int16 n )
    {
    	return (n * 65536);
    }
    
    Int24 x = 29;
    
    Int32 y = SomeFuncThatRequiresA16BitInt ((Int16) x );
    Last edited by John E; March 20th, 2004 at 06:36 AM.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  2. #2
    Join Date
    Nov 2003
    Location
    Vienna, Austria
    Posts
    212
    You have to emulate it. 64-bit operations are supported on some machines, emulated by the compiler on others. 32-bit operations are supported nearly everywhere. 24 bits are an odd number of bytes, leading to inefficiencies were they supported. Thus you need to emulate them or, better, use 32-bit numbers.
    All the buzzt
    CornedBee

  3. #3
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557
    The only reason to use 24-bit integers as opposed to 32-bit integers is due to issues regarding critical storage space.

    This happens in my developments sometimes.

    In order to emulate 24-bit native support, I usually use a data array of 3 bytes. The low word of the array holds the lower 16-bits and the single low byte of the single high 8-bit 'word' holds the upper 8-bits. Do all of the mathematics using standard 32-bit integers. Convert the results of the 32-bit integer calculations to the 3-byte storage scheme.

    You can set this up in a clean C++ class if you want. Most compilers will align the size of such a class to 4 bytes anyway, so you might have to force single-byte alignment.

    If you really want to do it, then I could work out some examples next week. I've got some stuff written in ANSI C related for this also.

    Sincerely, Chris.

    You're gonna go blind staring into that box all day.

  4. #4
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835
    Thanks CornedBee but I guess what I'm asking is whether anyone has any code for emulating 24 bit ints. Using 32 bit ints isn't viable because of lack of overflow checking - e.g.

    typedef long Int24;

    Int24 x = 8400000; // This would result in a value for 'x' of 8400000, which would be invalid for a genuine, signed 24 bit int.

    My "gut feeling" is that someone, somewhere must have solved this problem before.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  5. #5
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835
    Thanks for the offer Chris. The main reason I need this is to carry out signal processing on an audio stream. Audio streams are typically 8, 16 or 24 bit data so there's an immediate problem with 24 bit data because it has an 'unsupported' number of bytes per sample. A further problem with audio is that some systems use little-endian byte ordering and some use big-endian. Therefore, if the audio is 24 bit, I'm tryng to find some way of extracting exactly 3 bytes of data (per sample) for processing. Because of the byte ordering problem I'd need to do this, ideally, without an erroneous fourth byte.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  6. #6
    Join Date
    May 1999
    Location
    Southern California
    Posts
    12,266

  7. #7
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557
    John,

    In addition to all the comments so far, it sounds like you really don't need the 'full-blown' 24-bit integer solution that I sometimes use for tightly packed embedded systems.

    Simple get and put functions with some range checking might be sufficient.

    Take a look at this sample below which shows an example for a rudimentary get function. There is some basic support for the two styles of endedness.

    Maybe this will get you started.

    Sincerely, Chris.

    P.S. The casting back and forth has a sensible foundation and should not be neglected.



    Code:
    #include <iostream>
    
    typedef   signed char INT8;
    typedef   signed int  INT32;
    typedef unsigned char UINT8;
    typedef unsigned int  UINT32;
    
    const INT32 get_n24(const UINT8* p, const bool b_little_endian = true)
    {
      INT32 n;
      
      if(b_little_endian)
      {
        n =   (static_cast< INT32>(static_cast<INT8>(p[2])) * 0x10000)
            | (static_cast<UINT32>(p[1]) * 0x100)
            |  static_cast<UINT32>(p[0]);
      }
      else
      {
        n =   (static_cast< INT32>(static_cast<INT8>(p[0])) * 0x10000)
            | (static_cast<UINT32>(p[1]) * 0x100)
            |  static_cast<UINT32>(p[2]);
      }
      
      return n;
    }
    
    int main(int argc, char* argv[])
    {
      UINT8 data[3] = { 0xFF, 0xFF, 0xAF };
      
      INT32 n32 = ::get_n24(data);
      
      ::std::cout << n32 << ::std::endl;
      
      return 0;
    }
    You're gonna go blind staring into that box all day.

  8. #8
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835
    Thanks guys. I'll look at your suggestions, later today. In the meantime, I thought of an alternative approach. Does anybody understand the mechanism whereby CString (a class) can represent itself as though it was a LPCTSTR?

    Ideally, that's what I need. A class that can "disguise itself" as though it were an integer - but whose operators (+, -, = etc) could all be overloaded to simulate 24 bit arithmetic. If CString can pretend to be a const TCHAR*, it must be possible for other classes to do something similar.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  9. #9
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557
    John,

    You are talking about the cast operator from CString to char*. In my opinion, this is not the way to go. I do not think that the use of strings for 24-bit numeric manipulation is effective.

    Why don't you just write an int24 class based on three bytes with a possible sign flag? You can overload all the arithmetic operators in a very effective and clean fashion.

    Do you know how to do this? If not, I'll be happy to write a few lines for you to get you started.

    One question first: Are the 24-bit integers signed or unsigned?

    Sincerely, Chris.

    You're gonna go blind staring into that box all day.

  10. #10
    John E is offline Elite Member Power Poster
    Join Date
    Apr 2001
    Location
    Manchester, England
    Posts
    4,835
    Hi Chris - thanks for your help with this.

    I was only using CString as an example of a class that can disguise itself as TCHAR*. I didn't mean to imply that the maths should be done using strings. Sorry for any confustion.

    I should be okay with creating a class and overloading its operators. The bit I don't understand is how to make a class pass itself off as a specified type, like CString can do.

    If you look in my original post, I gave an example of how the custom Int24 variable would need to limit itself to 24 bit arithmetic and should also be "passable" to functions that require an integer. In a perfect world it would also store its data in 3 bytes, if possible. If you've got any code that could start me off I'd be very grateful. You don't need to worry about dealing with the 24 bit math limitations. I'll be able to code that myself.

    Incidentally, I need to handle both signed and unsigned data - although my inclination was to have different custom variables for each.
    "A problem well stated is a problem half solved.” - Charles F. Kettering

  11. #11
    Join Date
    Nov 2003
    Location
    Vienna, Austria
    Posts
    212
    It looks like this:
    Code:
    class int24
    {
      int value;
    
    public:
      int24() {}
      int24(const int24 &o) { value = o.value; }
      int24(int i) { //bounds check and assign }
      ...
    
      operator int() { return value; }
    
      int24 &operator =(const int24 &o) {
        value = o.value;
        return *this;
      }
      int24 &operator =(int i) {
        // bounds check and assign
      }
      ...
    };
    All the buzzt
    CornedBee

  12. #12
    Join Date
    May 1999
    Location
    Southern California
    Posts
    12,266
    In the definition of CString (in afx.h) is:
    Code:
    operator LPCTSTR() const;
    In afx.inl is:
    Code:
    _AFX_INLINE CString::operator LPCTSTR() const
      { return m_pchData; }
    That means that LPCTSTR for CString works in the manner that the "operator int" works for CornedBee's int24 class.
    "Signature":
    My web site is Simple Samples.
    C# Corner Editor

  13. #13
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557
    OK let's finish this one.

    John,

    Corned Bee and Sam Hobbs have added the stuff about the casting operator.

    I've got the source for 24-bit integer. It is attatched below in the form of full source code. Intentionally all cast overwrites are left out. So if you want 'em you'll have to add 'em.

    I extracted this work from some of my other developments. I've been meaning to do this for quite some time now and this post kick-started me. This code is absolutely new and it has not been verified significantly.

    Take a look. The syntax and algorithms will be usefull. Or you might simply take the entire class.

    Sincerely, Chris.

    Attached Files Attached Files
    You're gonna go blind staring into that box all day.

  14. #14
    Join Date
    May 1999
    Location
    Southern California
    Posts
    12,266
    Originally posted by dude_1967
    Intentionally all cast overwrites are left out.
    For C++ programmers, überschreiben usually means override, not overwrite. I don't know German but I can tell from the context when the word should be override instead of overwrite. Read my little Overwriting for a bit more.
    Last edited by Sam Hobbs; March 21st, 2004 at 01:14 PM.
    "Signature":
    My web site is Simple Samples.
    C# Corner Editor

  15. #15
    Join Date
    Nov 2003
    Location
    Vienna, Austria
    Posts
    212
    Yes, Sam is right. In the context of classes, überschreiben should be override.
    All the buzzt
    CornedBee

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured