<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

use std::ops::{Add, AddAssign, BitAnd, BitOr, Mul, Sub, Shl, ShlAssign, Shr};
use std::io;

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

/// An abstraction trait for keeping different sized integers.
pub trait Sample: PartialEq + Eq + Sized + Clone + Copy +
                  Add<Output = Self> + AddAssign +
                  BitAnd<Self, Output = Self> + BitOr<Self, Output = Self> +
                  Mul<Output = Self> + Shl<u32, Output = Self>  +
                  ShlAssign<u32> + Shr<u32, Output = Self> +
                  Shr<i8, Output = Self> + Shr<i32, Output = Self> +
                  Sub<Output = Self> {
  /// The normal size for the current a `Sample`.
  type Normal;

  /// The size, in bits, for the `Sample::Normal`.
  fn size() -> usize;

  /// The size, in bits, for the `Sample`.
  fn size_extended() -> usize;

  /// Convert the extended `Sample` to the normal.
  fn to_normal(sample: Self) -> Option<Self::Normal>;

  /// Convert an i8 into a `Sample`.
  fn from_i8(sample: i8) -> Self;

  /// Convert an i16 into a `Sample`.
  fn from_i16(sample: i16) -> Self;

  /// Convert an i32 into a `Sample`.
  ///
  /// With `Sample` sometimes being smaller than a i32, there is a chance
  /// for this function to return an incorrect number. So when the number is
  /// larger of smaller than the current `Sample`, it returns `None`
  /// otherwise `Some(sample)`.
  fn from_i32(sample: i32) -> Option<Self>;

  /// Convert an i32 into a `Sample`.
  fn from_i32_lossy(sample: i32) -> Self;
}

/// A trait for defining the size of a sample.
pub trait SampleSize {
  /// The internal integer size used with `Stream::iter`.
  ///
  /// Rather than making the user of `Stream::iter` will remember what the
  /// extended size of the output sample will be, this is to map to the
  /// value based on the current integer size used.
  type Extended: Sample;
}

impl SampleSize for i8 {
  type Extended = i16;
}

impl SampleSize for i16 {
  type Extended = i32;
}

impl SampleSize for i32 {
  type Extended = i64;
}

pub trait WriteExtension: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()>;

  fn write_be_u16(&mut self, number: u16) -> io::Result<()>;
  fn write_le_u16(&mut self, number: u16) -> io::Result<()>;

  fn write_be_u24(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u24(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u32(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u32(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u64(&mut self, number: u64) -> io::Result<()>;
  fn write_le_u64(&mut self, number: u64) -> io::Result<()>;
}

impl<Write> WriteExtension for Write where Write: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()> {
    self.write_all(&[number])
  }

  fn write_be_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[0] = (number >> 8) as u8;
    buffer[1] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[2] = number as u8;
    buffer[1] = (number >> 8) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = (number >> 16) as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = (number >> 24) as u8;
    buffer[1] = (number >> 16) as u8;
    buffer[2] = (number >> 8) as u8;
    buffer[3] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = (number >> 56) as u8;
    buffer[1] = (number >> 48) as u8;
    buffer[2] = (number >> 40) as u8;
    buffer[3] = (number >> 32) as u8;
    buffer[4] = (number >> 24) as u8;
    buffer[5] = (number >> 16) as u8;
    buffer[6] = (number >> 8) as u8;
    buffer[7] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;
    buffer[4] = (number >> 32) as u8;
    buffer[5] = (number >> 40) as u8;
    buffer[6] = (number >> 48) as u8;
    buffer[7] = (number >> 56) as u8;

    self.write_all(&buffer)
  }
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<commit_msg>Add test for `WriteExtension::write_u8`<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

use std::ops::{Add, AddAssign, BitAnd, BitOr, Mul, Sub, Shl, ShlAssign, Shr};
use std::io;

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

/// An abstraction trait for keeping different sized integers.
pub trait Sample: PartialEq + Eq + Sized + Clone + Copy +
                  Add<Output = Self> + AddAssign +
                  BitAnd<Self, Output = Self> + BitOr<Self, Output = Self> +
                  Mul<Output = Self> + Shl<u32, Output = Self>  +
                  ShlAssign<u32> + Shr<u32, Output = Self> +
                  Shr<i8, Output = Self> + Shr<i32, Output = Self> +
                  Sub<Output = Self> {
  /// The normal size for the current a `Sample`.
  type Normal;

  /// The size, in bits, for the `Sample::Normal`.
  fn size() -> usize;

  /// The size, in bits, for the `Sample`.
  fn size_extended() -> usize;

  /// Convert the extended `Sample` to the normal.
  fn to_normal(sample: Self) -> Option<Self::Normal>;

  /// Convert an i8 into a `Sample`.
  fn from_i8(sample: i8) -> Self;

  /// Convert an i16 into a `Sample`.
  fn from_i16(sample: i16) -> Self;

  /// Convert an i32 into a `Sample`.
  ///
  /// With `Sample` sometimes being smaller than a i32, there is a chance
  /// for this function to return an incorrect number. So when the number is
  /// larger of smaller than the current `Sample`, it returns `None`
  /// otherwise `Some(sample)`.
  fn from_i32(sample: i32) -> Option<Self>;

  /// Convert an i32 into a `Sample`.
  fn from_i32_lossy(sample: i32) -> Self;
}

/// A trait for defining the size of a sample.
pub trait SampleSize {
  /// The internal integer size used with `Stream::iter`.
  ///
  /// Rather than making the user of `Stream::iter` will remember what the
  /// extended size of the output sample will be, this is to map to the
  /// value based on the current integer size used.
  type Extended: Sample;
}

impl SampleSize for i8 {
  type Extended = i16;
}

impl SampleSize for i16 {
  type Extended = i32;
}

impl SampleSize for i32 {
  type Extended = i64;
}

pub trait WriteExtension: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()>;

  fn write_be_u16(&mut self, number: u16) -> io::Result<()>;
  fn write_le_u16(&mut self, number: u16) -> io::Result<()>;

  fn write_be_u24(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u24(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u32(&mut self, number: u32) -> io::Result<()>;
  fn write_le_u32(&mut self, number: u32) -> io::Result<()>;

  fn write_be_u64(&mut self, number: u64) -> io::Result<()>;
  fn write_le_u64(&mut self, number: u64) -> io::Result<()>;
}

impl<Write> WriteExtension for Write where Write: io::Write {
  fn write_u8(&mut self, number: u8) -> io::Result<()> {
    self.write_all(&[number])
  }

  fn write_be_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[0] = (number >> 8) as u8;
    buffer[1] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u16(&mut self, number: u16) -> io::Result<()> {
    let mut buffer = [0; 2];

    buffer[2] = number as u8;
    buffer[1] = (number >> 8) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = (number >> 16) as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u24(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 3];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = (number >> 24) as u8;
    buffer[1] = (number >> 16) as u8;
    buffer[2] = (number >> 8) as u8;
    buffer[3] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u32(&mut self, number: u32) -> io::Result<()> {
    let mut buffer = [0; 4];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;

    self.write_all(&buffer)
  }

  fn write_be_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = (number >> 56) as u8;
    buffer[1] = (number >> 48) as u8;
    buffer[2] = (number >> 40) as u8;
    buffer[3] = (number >> 32) as u8;
    buffer[4] = (number >> 24) as u8;
    buffer[5] = (number >> 16) as u8;
    buffer[6] = (number >> 8) as u8;
    buffer[7] = number as u8;

    self.write_all(&buffer)
  }

  fn write_le_u64(&mut self, number: u64) -> io::Result<()> {
    let mut buffer = [0; 8];

    buffer[0] = number as u8;
    buffer[1] = (number >> 8) as u8;
    buffer[2] = (number >> 16) as u8;
    buffer[3] = (number >> 24) as u8;
    buffer[4] = (number >> 32) as u8;
    buffer[5] = (number >> 40) as u8;
    buffer[6] = (number >> 48) as u8;
    buffer[7] = (number >> 56) as u8;

    self.write_all(&buffer)
  }
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }

  #[test]
  fn test_write_u8() {
    let mut buffer = [0; 1];

    assert!((&mut buffer[..]).write_u8(0xa0).is_ok());
    assert_eq!(buffer, [0xa0]);

    assert!((&mut buffer[..]).write_u8(0xff).is_ok());
    assert_eq!(buffer, [0xff]);

    assert!((&mut buffer[..]).write_u8(0x10).is_ok());
    assert_eq!(buffer, [0x10]);
  }
}
<|endoftext|>


<commit_before><commit_msg>Extraction section of install module partially done<commit_after>extern crate tar;
extern crate flate2;

use std::fs::File;
use std::io::{BufReader, Read, Write};
use std::path::Path;

use self::tar::Archive;
use self::flate2::read::GzDecoder;

fn extract_tar(input: &Path, output: &Path) {
    let file = File::open(input).unwrap();
    let mut archive = Archive::new(file);
    archive.unpack(output).unwrap();
}

fn extract_gz(input: &Path, output: &Path) {
    let file = File::open(input).unwrap();
    let buffer = BufReader::new(file);
    let archive = GzDecoder::new(buffer).unwrap();

    let mut buffer = File::create(output).unwrap();
    for byte in archive.bytes() {
        buffer.write(byte.unwrap());
    }
}<|endoftext|>


<commit_before>use caches::art_cache::ArtCache;
use caches::texmap_cache::TexMapCache;
use caches::facet_cache::Altitudes;
use cgmath::Point2;
use ggez::event::{KeyCode, KeyMods};
use ggez::graphics::{self, DrawParam};
use ggez::{Context, GameResult};
use map::{map_id_to_facet, Facet, MAP_DETAILS};
use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use uorustlibs::map::{Block, StaticLocation};

const STEP_X: u32 = 1;
const STEP_Y: u32 = 1;
const MAX_BLOCKS_WIDTH: u32 = 6;
const MAX_BLOCKS_HEIGHT: u32 = 6;

pub struct WorldScene {
    art_cache: ArtCache,
    texmap_cache: TexMapCache,
    facet: Facet,
    x: u32,
    y: u32,
    map_id: u8,
    exiting: bool,
}

fn add(a: Point2<f32>, b: Point2<f32>) -> Point2<f32> {
    Point2::new(a.x + b.x, a.y + b.y)
}

fn cell_at(x: i32, y: i32) -> Point2<f32> {
    Point2::new(
        ((22 * 7) + (22 * x) - (y * 22)) as f32,
        ((22 * y) + (x * 22)) as f32,
    )
}

// TODO: Make this less nasty
fn block_at(x: i32, y: i32) -> Point2<f32> {
    Point2::new(
        ((22 * 8) * x - (y * (22 * 8)) + (22 * 16)) as f32,
        ((22 * 8) * y + (x * (22 * 8)) - (22 * 24)) as f32,
    )
}

impl<'a> WorldScene {
    pub fn new() -> BoxedScene<'a, SceneName, ()> {
        let scene = Box::new(WorldScene {
            exiting: false,
            map_id: 0,
            facet: map_id_to_facet(0),
            art_cache: ArtCache::new(),
            texmap_cache: TexMapCache::new(),
            x: 70,
            y: 70
        });
        scene
    }

    pub fn draw_page(&mut self, ctx: &mut Context) -> GameResult<()> {
        for y in 0..MAX_BLOCKS_HEIGHT {
            for x in 0..MAX_BLOCKS_WIDTH {
                let ((ref block, ref statics), ref altitudes) = self.facet.read_block(x + self.x, y + self.y);
                let transform = block_at(x as i32, y as i32);
                self.draw_block(ctx, block, statics, altitudes, transform)?
            }
        }
        Ok(())
    }

    pub fn draw_block(
        &mut self,
        ctx: &mut Context,
        block: &Block,
        _statics: &Vec<StaticLocation>,
        altitudes: &Vec<Altitudes>,
        transform: Point2<f32>,
    ) -> GameResult<()> {
        for y in 0..8 {
            for x in 0..8 {
                let cell = block.cells[y * 8 + x];
                let altitudes = altitudes[y * 8 + x];
                let cell_height = altitudes.x1y1;
                let cell_x2y1_height = altitudes.x2y1;
                let cell_x1y2_height = altitudes.x1y2;
                let cell_x2y2_height = altitudes.x2y2;
                if (cell_height == cell_x1y2_height && cell.altitude == cell_x2y1_height && cell.altitude == cell_x2y2_height) {
                    self.art_cache
                        .read_tile(ctx, cell.graphic as u32)
                        .as_ref()
                        .map(|tile| {
                                let new_transform = add(
                                    add(cell_at(x as i32, y as i32), transform),
                                    Point2::new(0.0, -cell.altitude as f32)
                                );
                                graphics::draw(ctx, tile, DrawParam::default().dest(new_transform))
                                })
                    .unwrap_or(Ok(()))?;
                } else {
                    self.texmap_cache
                        .read_texmap(ctx, cell.graphic as u32)
                        .as_ref()
                        .map(|tile| {
                                let new_transform = add(
                                        add(cell_at(x as i32, y as i32), transform),
                                        Point2::new(0.0, -cell.altitude as f32),
                                        );
                                graphics::draw(ctx, tile, DrawParam::default().dest(new_transform))
                                })
                    .unwrap_or(Ok(()))?;
                }
            }
        }
        Ok(())
    }
}

impl Scene<SceneName, ()> for WorldScene {
    fn draw(&mut self, ctx: &mut Context, _engine_data: &mut ()) -> GameResult<()> {
        graphics::clear(ctx, graphics::BLACK);
        self.draw_page(ctx)
    }

    fn key_down_event(
        &mut self,
        _ctx: &mut Context,
        keycode: KeyCode,
        _keymods: KeyMods,
        _repeat: bool,
        _engine_data: &mut (),
    ) {
        match keycode {
            KeyCode::Escape => self.exiting = true,
            KeyCode::Left => {
                if self.x >= STEP_X as u32 {
                    self.x -= STEP_X as u32;
                }
            }
            KeyCode::Right => {
                self.x += STEP_X as u32;
            }
            KeyCode::Up => {
                if self.y >= STEP_Y as u32 {
                    self.y -= STEP_Y as u32;
                }
            }
            KeyCode::Down => {
                self.y += STEP_Y as u32;
            }
            KeyCode::Tab => {
                self.map_id = (self.map_id + 1) % MAP_DETAILS.len() as u8;
                self.facet = map_id_to_facet(self.map_id);
                self.x = 0;
                self.y = 0;
            }
            _ => (),
        }
    }

    fn update(
        &mut self,
        _ctx: &mut Context,
        _engine_data: &mut (),
    ) -> GameResult<Option<SceneChangeEvent<SceneName>>> {
        if self.exiting {
            Ok(Some(SceneChangeEvent::PopScene))
        } else {
            Ok(None)
        }
    }
}
<commit_msg>Resizing texture maps to the correct size<commit_after>use caches::art_cache::ArtCache;
use caches::texmap_cache::TexMapCache;
use caches::facet_cache::Altitudes;
use cgmath::Point2;
use ggez::event::{KeyCode, KeyMods};
use ggez::graphics::{self, DrawParam, Skewable};
use ggez::{Context, GameResult};
use map::{map_id_to_facet, Facet, MAP_DETAILS};
use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use uorustlibs::map::{Block, StaticLocation};

const STEP_X: u32 = 1;
const STEP_Y: u32 = 1;
const MAX_BLOCKS_WIDTH: u32 = 6;
const MAX_BLOCKS_HEIGHT: u32 = 6;

pub struct WorldScene {
    art_cache: ArtCache,
    texmap_cache: TexMapCache,
    facet: Facet,
    x: u32,
    y: u32,
    map_id: u8,
    exiting: bool,
}

fn add(a: Point2<f32>, b: Point2<f32>) -> Point2<f32> {
    Point2::new(a.x + b.x, a.y + b.y)
}

fn cell_at(x: i32, y: i32) -> Point2<f32> {
    Point2::new(
        ((22 * 7) + (22 * x) - (y * 22)) as f32,
        ((22 * y) + (x * 22)) as f32,
    )
}

// TODO: Make this less nasty
fn block_at(x: i32, y: i32) -> Point2<f32> {
    Point2::new(
        ((22 * 8) * x - (y * (22 * 8)) + (22 * 16)) as f32,
        ((22 * 8) * y + (x * (22 * 8)) - (22 * 24)) as f32,
    )
}

impl<'a> WorldScene {
    pub fn new() -> BoxedScene<'a, SceneName, ()> {
        let scene = Box::new(WorldScene {
            exiting: false,
            map_id: 0,
            facet: map_id_to_facet(0),
            art_cache: ArtCache::new(),
            texmap_cache: TexMapCache::new(),
            x: 160,
            y: 208
        });
        scene
    }

    pub fn draw_page(&mut self, ctx: &mut Context) -> GameResult<()> {
        for y in 0..MAX_BLOCKS_HEIGHT {
            for x in 0..MAX_BLOCKS_WIDTH {
                let ((ref block, ref statics), ref altitudes) = self.facet.read_block(x + self.x, y + self.y);
                let transform = block_at(x as i32, y as i32);
                self.draw_block(ctx, block, statics, altitudes, transform)?
            }
        }
        Ok(())
    }

    pub fn draw_block(
        &mut self,
        ctx: &mut Context,
        block: &Block,
        _statics: &Vec<StaticLocation>,
        altitudes: &Vec<Altitudes>,
        transform: Point2<f32>,
    ) -> GameResult<()> {
        for y in 0..8 {
            for x in 0..8 {
                let cell = block.cells[y * 8 + x];
                let altitudes = altitudes[y * 8 + x];
                let cell_height = altitudes.x1y1;
                let cell_x2y1_height = altitudes.x2y1;
                let cell_x1y2_height = altitudes.x1y2;
                let cell_x2y2_height = altitudes.x2y2;
                if (cell_height == cell_x1y2_height && cell.altitude == cell_x2y1_height && cell.altitude == cell_x2y2_height) {
                    self.art_cache
                        .read_tile(ctx, cell.graphic as u32)
                        .as_ref()
                        .map(|tile| {
                            let new_transform = add(
                                add(cell_at(x as i32, y as i32), transform),
                                Point2::new(0.0, -cell.altitude as f32)
                            );
                            graphics::draw(ctx, tile, DrawParam::default().dest(new_transform))
                        })
                        .unwrap_or(Ok(()))?;
                } else {
                    self.texmap_cache
                        .read_texmap(ctx, cell.graphic as u32)
                        .as_ref()
                        .map(|tile| {
                            let skewed = if (tile.width() == 64) {
                                Skewable::new(ctx, tile.clone(), [[0.5 * 0.6875, 0.0], [1.0 * 0.6875, 0.50 * 0.6875], [0.5 * 0.6875, 1.0 * 0.6875], [0.0, 0.5 * 0.6875]])
                            } else {
                                Skewable::new(ctx, tile.clone(), [[0.5 * 0.34375, 0.0], [1.0 * 0.34375, 0.50 * 0.34375], [0.5 * 0.34375, 1.0 * 0.34375], [0.0, 0.5 * 0.34375]])
                            };
                            let new_transform = add(
                                add(cell_at(x as i32, y as i32), transform),
                                Point2::new(0.0, -cell.altitude as f32),
                            );
                            graphics::draw(ctx, &skewed, DrawParam::default().dest(new_transform))
                        })
                        .unwrap_or(Ok(()))?;
                }
            }
        }
        Ok(())
    }
}

impl Scene<SceneName, ()> for WorldScene {
    fn draw(&mut self, ctx: &mut Context, _engine_data: &mut ()) -> GameResult<()> {
        graphics::clear(ctx, graphics::BLACK);
        self.draw_page(ctx)
    }

    fn key_down_event(
        &mut self,
        _ctx: &mut Context,
        keycode: KeyCode,
        _keymods: KeyMods,
        _repeat: bool,
        _engine_data: &mut (),
    ) {
        match keycode {
            KeyCode::Escape => self.exiting = true,
            KeyCode::Left => {
                if self.x >= STEP_X as u32 {
                    self.x -= STEP_X as u32;
                }
            }
            KeyCode::Right => {
                self.x += STEP_X as u32;
            }
            KeyCode::Up => {
                if self.y >= STEP_Y as u32 {
                    self.y -= STEP_Y as u32;
                }
            }
            KeyCode::Down => {
                self.y += STEP_Y as u32;
            }
            KeyCode::Tab => {
                self.map_id = (self.map_id + 1) % MAP_DETAILS.len() as u8;
                self.facet = map_id_to_facet(self.map_id);
                self.x = 0;
                self.y = 0;
            }
            _ => (),
        }
    }

    fn update(
        &mut self,
        _ctx: &mut Context,
        _engine_data: &mut (),
    ) -> GameResult<Option<SceneChangeEvent<SceneName>>> {
        if self.exiting {
            Ok(Some(SceneChangeEvent::PopScene))
        } else {
            Ok(None)
        }
    }
}
<|endoftext|>


<commit_before>use std::{slice};

use libc::{c_uint, size_t, c_int};

use katajainen::length_limited_code_lengths;

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliLengthsToSymbols(lengths_ptr: *const c_uint, n: size_t, maxbits: c_uint, symbols: *mut c_uint) {
    let lengths = unsafe { slice::from_raw_parts(lengths_ptr, n) };
    let mut bl_count = vec![0; (maxbits + 1) as usize];
    let mut next_code = vec![0; (maxbits + 1) as usize];

    for i in 0..n {
        unsafe {
            *symbols.offset(i as isize) = 0;
        }
    }

    // 1) Count the number of codes for each code length. Let bl_count[N] be the
    // number of codes of length N, N >= 1. */
    for i in 0..n {
        assert!(lengths[i] <= maxbits);
        bl_count[lengths[i] as usize] += 1;
    }
    // 2) Find the numerical value of the smallest code for each code length.
    let mut code = 0;
    bl_count[0] = 0;
    for bits in 1..(maxbits + 1) {
        code = (code + bl_count[(bits - 1) as usize]) << 1;
        next_code[bits as usize] = code;
    }
    // 3) Assign numerical values to all codes, using consecutive values for all
    // codes of the same length with the base values determined at step 2.
    for i in 0..n {
        let len = lengths[i] as usize;
        if len != 0 {
            unsafe {
                *symbols.offset(i as isize) = next_code[len];
            }
            next_code[len] += 1;
        }
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliCalculateBitLengths(frequencies: *const size_t, n: usize, maxbits: c_int, bitlengths: *mut c_uint) {
    let freqs = unsafe { slice::from_raw_parts(frequencies, n) };
    let result = length_limited_code_lengths(freqs, maxbits);

    for (i, res) in result.into_iter().enumerate() {
        unsafe {
            *bitlengths.offset(i as isize) = res as c_uint;
        }
    }
}
<commit_msg>Make ZopfliLengthsToSymbols just wrap a more rusty fn<commit_after>use std::{slice};

use libc::{c_uint, size_t, c_int};

use katajainen::length_limited_code_lengths;

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliLengthsToSymbols(lengths_ptr: *const c_uint, n: size_t, maxbits: c_uint, symbols: *mut c_uint) {
    let lengths = unsafe { slice::from_raw_parts(lengths_ptr, n) };
    let lengths_size_t = lengths.iter().map(|&len| len as size_t).collect::<Vec<_>>();

    let syms = lengths_to_symbols(&lengths_size_t, maxbits);
    for i in 0..n {
        unsafe {
            *symbols.offset(i as isize) = syms[i];
        }
    }
}

pub fn lengths_to_symbols(lengths: &[size_t], maxbits: c_uint) -> Vec<c_uint> {
    let mut bl_count = vec![0; (maxbits + 1) as usize];
    let mut next_code = vec![0; (maxbits + 1) as usize];
    let n = lengths.len();

    let mut symbols = vec![0; n];

    // 1) Count the number of codes for each code length. Let bl_count[N] be the
    // number of codes of length N, N >= 1. */
    for i in 0..n {
        assert!(lengths[i] <= maxbits as usize);
        bl_count[lengths[i] as usize] += 1;
    }
    // 2) Find the numerical value of the smallest code for each code length.
    let mut code = 0;
    bl_count[0] = 0;
    for bits in 1..(maxbits + 1) {
        code = (code + bl_count[(bits - 1) as usize]) << 1;
        next_code[bits as usize] = code;
    }
    // 3) Assign numerical values to all codes, using consecutive values for all
    // codes of the same length with the base values determined at step 2.
    for i in 0..n {
        let len = lengths[i] as usize;
        if len != 0 {
            symbols[i] = next_code[len];
            next_code[len] += 1;
        }
    }
    symbols
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ZopfliCalculateBitLengths(frequencies: *const size_t, n: usize, maxbits: c_int, bitlengths: *mut c_uint) {
    let freqs = unsafe { slice::from_raw_parts(frequencies, n) };
    let result = length_limited_code_lengths(freqs, maxbits);

    for (i, res) in result.into_iter().enumerate() {
        unsafe {
            *bitlengths.offset(i as isize) = res as c_uint;
        }
    }
}
<|endoftext|>


<commit_before>//! Codegen `extern "platform-intrinsic"` intrinsics.

use super::*;
use crate::prelude::*;

pub(super) fn codegen_simd_intrinsic_call<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    instance: Instance<'tcx>,
    args: &[mir::Operand<'tcx>],
    ret: CPlace<'tcx>,
    span: Span,
) {
    let def_id = instance.def_id();
    let substs = instance.substs;

    let intrinsic = fx.tcx.item_name(def_id);

    intrinsic_match! {
        fx, intrinsic, substs, args,
        _ => {
            fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic));
        };

        simd_cast, (c a) {
            validate_simd_type!(fx, intrinsic, span, a.layout().ty);
            simd_for_each_lane(fx, a, ret, |fx, lane_layout, ret_lane_layout, lane| {
                let ret_lane_ty = fx.clif_type(ret_lane_layout.ty).unwrap();

                let from_signed = type_sign(lane_layout.ty);
                let to_signed = type_sign(ret_lane_layout.ty);

                let ret_lane = clif_int_or_float_cast(fx, lane, from_signed, ret_lane_ty, to_signed);
                CValue::by_val(ret_lane, ret_lane_layout)
            });
        };

        simd_eq, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, Equal|Equal(x, y) -> ret);
        };
        simd_ne, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, NotEqual|NotEqual(x, y) -> ret);
        };
        simd_lt, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, UnsignedLessThan|SignedLessThan|LessThan(x, y) -> ret);
        };
        simd_le, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, UnsignedLessThanOrEqual|SignedLessThanOrEqual|LessThanOrEqual(x, y) -> ret);
        };
        simd_gt, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, UnsignedGreaterThan|SignedGreaterThan|GreaterThan(x, y) -> ret);
        };
        simd_ge, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(
                fx,
                UnsignedGreaterThanOrEqual|SignedGreaterThanOrEqual|GreaterThanOrEqual
                (x, y) -> ret
            );
        };

        // simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U
        _ if intrinsic.as_str().starts_with("simd_shuffle"), (c x, c y, o idx) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);

            let n: u16 = intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap();

            assert_eq!(x.layout(), y.layout());
            let layout = x.layout();

            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);

            assert_eq!(lane_ty, ret_lane_ty);
            assert_eq!(u64::from(n), ret_lane_count);

            let total_len = lane_count * 2;

            let indexes = {
                use rustc_middle::mir::interpret::*;
                let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const");

                let idx_bytes = match idx_const {
                    ConstValue::ByRef { alloc, offset } => {
                        let ptr = Pointer::new(AllocId(0 /* dummy */), offset);
                        let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */);
                        alloc.get_bytes(fx, ptr, size).unwrap()
                    }
                    _ => unreachable!("{:?}", idx_const),
                };

                (0..ret_lane_count).map(|i| {
                    let i = usize::try_from(i).unwrap();
                    let idx = rustc_middle::mir::interpret::read_target_uint(
                        fx.tcx.data_layout.endian,
                        &idx_bytes[4*i.. 4*i + 4],
                    ).expect("read_target_uint");
                    u16::try_from(idx).expect("try_from u32")
                }).collect::<Vec<u16>>()
            };

            for &idx in &indexes {
                assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len);
            }

            for (out_idx, in_idx) in indexes.into_iter().enumerate() {
                let in_lane = if u64::from(in_idx) < lane_count {
                    x.value_field(fx, mir::Field::new(in_idx.into()))
                } else {
                    y.value_field(fx, mir::Field::new(usize::from(in_idx) - usize::try_from(lane_count).unwrap()))
                };
                let out_lane = ret.place_field(fx, mir::Field::new(out_idx));
                out_lane.write_cvalue(fx, in_lane);
            }
        };

        simd_insert, (c base, o idx, c val) {
            // FIXME validate
            let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
                idx_const
            } else {
                fx.tcx.sess.span_fatal(
                    span,
                    "Index argument for `simd_insert` is not a constant",
                );
            };

            let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
            let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
            if idx >= lane_count.into() {
                fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count));
            }

            ret.write_cvalue(fx, base);
            let ret_lane = ret.place_field(fx, mir::Field::new(idx.try_into().unwrap()));
            ret_lane.write_cvalue(fx, val);
        };

        simd_extract, (c v, o idx) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
                idx_const
            } else {
                fx.tcx.sess.span_warn(
                    span,
                    "Index argument for `simd_extract` is not a constant",
                );
                let res = crate::trap::trap_unimplemented_ret_value(
                    fx,
                    ret.layout(),
                    "Index argument for `simd_extract` is not a constant",
                );
                ret.write_cvalue(fx, res);
                return;
            };

            let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
            let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
            if idx >= lane_count.into() {
                fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count));
            }

            let ret_lane = v.value_field(fx, mir::Field::new(idx.try_into().unwrap()));
            ret.write_cvalue(fx, ret_lane);
        };

        simd_add, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, iadd|fadd(x, y) -> ret);
        };
        simd_sub, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, isub|fsub(x, y) -> ret);
        };
        simd_mul, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, imul|fmul(x, y) -> ret);
        };
        simd_div, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, udiv|sdiv|fdiv(x, y) -> ret);
        };
        simd_shl, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, ishl(x, y) -> ret);
        };
        simd_shr, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, ushr|sshr(x, y) -> ret);
        };
        simd_and, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, band(x, y) -> ret);
        };
        simd_or, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, bor(x, y) -> ret);
        };
        simd_xor, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, bxor(x, y) -> ret);
        };

        simd_fma, (c a, c b, c c) {
            validate_simd_type!(fx, intrinsic, span, a.layout().ty);
            assert_eq!(a.layout(), b.layout());
            assert_eq!(a.layout(), c.layout());
            let layout = a.layout();

            let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
            assert_eq!(lane_count, ret_lane_count);
            let ret_lane_layout = fx.layout_of(ret_lane_ty);

            for lane in 0..lane_count {
                let lane = mir::Field::new(lane.try_into().unwrap());
                let a_lane = a.value_field(fx, lane).load_scalar(fx);
                let b_lane = b.value_field(fx, lane).load_scalar(fx);
                let c_lane = c.value_field(fx, lane).load_scalar(fx);

                let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane);
                let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout);

                ret.place_field(fx, lane).write_cvalue(fx, res_lane);
            }
        };

        simd_fmin, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_flt_binop!(fx, fmin(x, y) -> ret);
        };
        simd_fmax, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_flt_binop!(fx, fmax(x, y) -> ret);
        };

        simd_reduce_add_ordered | simd_reduce_add_unordered, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce(fx, v, ret, |fx, lane_layout, a, b| {
                if lane_layout.ty.is_floating_point() {
                    fx.bcx.ins().fadd(a, b)
                } else {
                    fx.bcx.ins().iadd(a, b)
                }
            });
        };

        simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce(fx, v, ret, |fx, lane_layout, a, b| {
                if lane_layout.ty.is_floating_point() {
                    fx.bcx.ins().fmul(a, b)
                } else {
                    fx.bcx.ins().imul(a, b)
                }
            });
        };

        simd_reduce_all, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().band(a, b));
        };

        simd_reduce_any, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().bor(a, b));
        };

        // simd_fabs
        // simd_saturating_add
        // simd_bitmask
        // simd_select
        // simd_rem
        // simd_neg
    }
}
<commit_msg>Sync from rust 6df26f897cffb2d86880544bb451c6b5f8509b2d<commit_after>//! Codegen `extern "platform-intrinsic"` intrinsics.

use super::*;
use crate::prelude::*;

pub(super) fn codegen_simd_intrinsic_call<'tcx>(
    fx: &mut FunctionCx<'_, '_, 'tcx>,
    instance: Instance<'tcx>,
    args: &[mir::Operand<'tcx>],
    ret: CPlace<'tcx>,
    span: Span,
) {
    let def_id = instance.def_id();
    let substs = instance.substs;

    let intrinsic = fx.tcx.item_name(def_id);

    intrinsic_match! {
        fx, intrinsic, substs, args,
        _ => {
            fx.tcx.sess.span_fatal(span, &format!("Unknown SIMD intrinsic {}", intrinsic));
        };

        simd_cast, (c a) {
            validate_simd_type!(fx, intrinsic, span, a.layout().ty);
            simd_for_each_lane(fx, a, ret, |fx, lane_layout, ret_lane_layout, lane| {
                let ret_lane_ty = fx.clif_type(ret_lane_layout.ty).unwrap();

                let from_signed = type_sign(lane_layout.ty);
                let to_signed = type_sign(ret_lane_layout.ty);

                let ret_lane = clif_int_or_float_cast(fx, lane, from_signed, ret_lane_ty, to_signed);
                CValue::by_val(ret_lane, ret_lane_layout)
            });
        };

        simd_eq, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, Equal|Equal(x, y) -> ret);
        };
        simd_ne, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, NotEqual|NotEqual(x, y) -> ret);
        };
        simd_lt, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, UnsignedLessThan|SignedLessThan|LessThan(x, y) -> ret);
        };
        simd_le, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, UnsignedLessThanOrEqual|SignedLessThanOrEqual|LessThanOrEqual(x, y) -> ret);
        };
        simd_gt, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(fx, UnsignedGreaterThan|SignedGreaterThan|GreaterThan(x, y) -> ret);
        };
        simd_ge, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_cmp!(
                fx,
                UnsignedGreaterThanOrEqual|SignedGreaterThanOrEqual|GreaterThanOrEqual
                (x, y) -> ret
            );
        };

        // simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U
        _ if intrinsic.as_str().starts_with("simd_shuffle"), (c x, c y, o idx) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);

            let n: u16 = intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap();

            assert_eq!(x.layout(), y.layout());
            let layout = x.layout();

            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);

            assert_eq!(lane_ty, ret_lane_ty);
            assert_eq!(u64::from(n), ret_lane_count);

            let total_len = lane_count * 2;

            let indexes = {
                use rustc_middle::mir::interpret::*;
                let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const");

                let idx_bytes = match idx_const {
                    ConstValue::ByRef { alloc, offset } => {
                        let ptr = Pointer::new(AllocId(0 /* dummy */), offset);
                        let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */);
                        alloc.get_bytes(fx, ptr, size).unwrap()
                    }
                    _ => unreachable!("{:?}", idx_const),
                };

                (0..ret_lane_count).map(|i| {
                    let i = usize::try_from(i).unwrap();
                    let idx = rustc_middle::mir::interpret::read_target_uint(
                        fx.tcx.data_layout.endian,
                        &idx_bytes[4*i.. 4*i + 4],
                    ).expect("read_target_uint");
                    u16::try_from(idx).expect("try_from u32")
                }).collect::<Vec<u16>>()
            };

            for &idx in &indexes {
                assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len);
            }

            for (out_idx, in_idx) in indexes.into_iter().enumerate() {
                let in_lane = if u64::from(in_idx) < lane_count {
                    x.value_field(fx, mir::Field::new(in_idx.into()))
                } else {
                    y.value_field(fx, mir::Field::new(usize::from(in_idx) - usize::try_from(lane_count).unwrap()))
                };
                let out_lane = ret.place_field(fx, mir::Field::new(out_idx));
                out_lane.write_cvalue(fx, in_lane);
            }
        };

        simd_insert, (c base, o idx, c val) {
            // FIXME validate
            let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
                idx_const
            } else {
                fx.tcx.sess.span_fatal(
                    span,
                    "Index argument for `simd_insert` is not a constant",
                );
            };

            let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
            let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
            if idx >= lane_count.into() {
                fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count));
            }

            ret.write_cvalue(fx, base);
            let ret_lane = ret.place_field(fx, mir::Field::new(idx.try_into().unwrap()));
            ret_lane.write_cvalue(fx, val);
        };

        simd_extract, (c v, o idx) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
                idx_const
            } else {
                fx.tcx.sess.span_warn(
                    span,
                    "Index argument for `simd_extract` is not a constant",
                );
                let res = crate::trap::trap_unimplemented_ret_value(
                    fx,
                    ret.layout(),
                    "Index argument for `simd_extract` is not a constant",
                );
                ret.write_cvalue(fx, res);
                return;
            };

            let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
            let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
            if idx >= lane_count.into() {
                fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count));
            }

            let ret_lane = v.value_field(fx, mir::Field::new(idx.try_into().unwrap()));
            ret.write_cvalue(fx, ret_lane);
        };

        simd_add, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, iadd|fadd(x, y) -> ret);
        };
        simd_sub, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, isub|fsub(x, y) -> ret);
        };
        simd_mul, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, imul|fmul(x, y) -> ret);
        };
        simd_div, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_flt_binop!(fx, udiv|sdiv|fdiv(x, y) -> ret);
        };
        simd_shl, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, ishl(x, y) -> ret);
        };
        simd_shr, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, ushr|sshr(x, y) -> ret);
        };
        simd_and, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, band(x, y) -> ret);
        };
        simd_or, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, bor(x, y) -> ret);
        };
        simd_xor, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_int_binop!(fx, bxor(x, y) -> ret);
        };

        simd_fma, (c a, c b, c c) {
            validate_simd_type!(fx, intrinsic, span, a.layout().ty);
            assert_eq!(a.layout(), b.layout());
            assert_eq!(a.layout(), c.layout());
            let layout = a.layout();

            let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
            assert_eq!(lane_count, ret_lane_count);
            let ret_lane_layout = fx.layout_of(ret_lane_ty);

            for lane in 0..lane_count {
                let lane = mir::Field::new(lane.try_into().unwrap());
                let a_lane = a.value_field(fx, lane).load_scalar(fx);
                let b_lane = b.value_field(fx, lane).load_scalar(fx);
                let c_lane = c.value_field(fx, lane).load_scalar(fx);

                let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane);
                let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout);

                ret.place_field(fx, lane).write_cvalue(fx, res_lane);
            }
        };

        simd_fmin, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_flt_binop!(fx, fmin(x, y) -> ret);
        };
        simd_fmax, (c x, c y) {
            validate_simd_type!(fx, intrinsic, span, x.layout().ty);
            simd_flt_binop!(fx, fmax(x, y) -> ret);
        };

        simd_reduce_add_ordered | simd_reduce_add_unordered, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce(fx, v, ret, |fx, lane_layout, a, b| {
                if lane_layout.ty.is_floating_point() {
                    fx.bcx.ins().fadd(a, b)
                } else {
                    fx.bcx.ins().iadd(a, b)
                }
            });
        };

        simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce(fx, v, ret, |fx, lane_layout, a, b| {
                if lane_layout.ty.is_floating_point() {
                    fx.bcx.ins().fmul(a, b)
                } else {
                    fx.bcx.ins().imul(a, b)
                }
            });
        };

        simd_reduce_all, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().band(a, b));
        };

        simd_reduce_any, (c v) {
            validate_simd_type!(fx, intrinsic, span, v.layout().ty);
            simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().bor(a, b));
        };

        // simd_fabs
        // simd_saturating_add
        // simd_bitmask
        // simd_select
        // simd_rem
        // simd_neg
        // simd_trunc
        // simd_floor
    }
}
<|endoftext|>


<commit_before>/// Creates a [`Vec`] containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a [`Vec`] containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a [`Vec`] from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement [`Clone`] and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
///
/// [`Vec`]: ../std/vec/struct.Vec.html
/// [`Clone`]: ../std/clone/trait.Clone.html
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => ($crate::vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Creates a `String` using interpolation of runtime expressions.
///
/// The first argument `format!` receives is a format string. This must be a string
/// literal. The power of the formatting string is in the `{}`s contained.
///
/// Additional parameters passed to `format!` replace the `{}`s within the
/// formatting string in the order given unless named or positional parameters
/// are used; see [`std::fmt`][fmt] for more information.
///
/// A common use for `format!` is concatenation and interpolation of strings.
/// The same convention is used with [`print!`] and [`write!`] macros,
/// depending on the intended destination of the string.
///
/// To convert a single value to a string, use the [`to_string`] method. This
/// will use the [`Display`] formatting trait.
///
/// [fmt]: ../std/fmt/index.html
/// [`print!`]: ../std/macro.print.html
/// [`write!`]: ../std/macro.write.html
/// [`to_string`]: ../std/string/trait.ToString.html
/// [`Display`]: ../std/fmt/trait.Display.html
///
/// # Panics
///
/// `format!` panics if a formatting trait implementation returns an error.
/// This indicates an incorrect implementation
/// since `fmt::Write for String` never returns an error itself.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => {{
        let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
        res
    }}
}
<commit_msg>expand vec![] to Vec::new()<commit_after>/// Creates a [`Vec`] containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a [`Vec`] containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a [`Vec`] from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement [`Clone`] and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
///
/// [`Vec`]: ../std/vec/struct.Vec.html
/// [`Clone`]: ../std/clone/trait.Clone.html
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax)]
macro_rules! vec {
    () => (
        $crate::vec::Vec::new()
    );
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => ($crate::vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    () => (
        $crate::vec::Vec::new()
    );
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Creates a `String` using interpolation of runtime expressions.
///
/// The first argument `format!` receives is a format string. This must be a string
/// literal. The power of the formatting string is in the `{}`s contained.
///
/// Additional parameters passed to `format!` replace the `{}`s within the
/// formatting string in the order given unless named or positional parameters
/// are used; see [`std::fmt`][fmt] for more information.
///
/// A common use for `format!` is concatenation and interpolation of strings.
/// The same convention is used with [`print!`] and [`write!`] macros,
/// depending on the intended destination of the string.
///
/// To convert a single value to a string, use the [`to_string`] method. This
/// will use the [`Display`] formatting trait.
///
/// [fmt]: ../std/fmt/index.html
/// [`print!`]: ../std/macro.print.html
/// [`write!`]: ../std/macro.write.html
/// [`to_string`]: ../std/string/trait.ToString.html
/// [`Display`]: ../std/fmt/trait.Display.html
///
/// # Panics
///
/// `format!` panics if a formatting trait implementation returns an error.
/// This indicates an incorrect implementation
/// since `fmt::Write for String` never returns an error itself.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => {{
        let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
        res
    }}
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Operations and constants for 32-bits floats (`f32` type)

#![doc(primitive = "f32")]
// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
#![allow(type_overflow)]

use intrinsics;
use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
use num::Float;
use option::Option;

pub static RADIX: uint = 2u;

pub static MANTISSA_DIGITS: uint = 24u;
pub static DIGITS: uint = 6u;

pub static EPSILON: f32 = 1.19209290e-07_f32;

/// Smallest finite f32 value
pub static MIN_VALUE: f32 = -3.40282347e+38_f32;
/// Smallest positive, normalized f32 value
pub static MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
/// Largest finite f32 value
pub static MAX_VALUE: f32 = 3.40282347e+38_f32;

pub static MIN_EXP: int = -125;
pub static MAX_EXP: int = 128;

pub static MIN_10_EXP: int = -37;
pub static MAX_10_EXP: int = 38;

pub static NAN: f32 = 0.0_f32/0.0_f32;
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
pub static NEG_INFINITY: f32 = -1.0_f32/0.0_f32;

/// Various useful constants.
pub mod consts {
    // FIXME: replace with mathematical constants from cmath.

    // FIXME(#5527): These constants should be deprecated once associated
    // constants are implemented in favour of referencing the respective members
    // of `Float`.

    /// Archimedes' constant
    pub static PI: f32 = 3.14159265358979323846264338327950288_f32;

    /// pi * 2.0
    pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;

    /// pi/2.0
    pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;

    /// pi/3.0
    pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;

    /// pi/4.0
    pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;

    /// pi/6.0
    pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;

    /// pi/8.0
    pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;

    /// 1.0/pi
    pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;

    /// 2.0/pi
    pub static FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;

    /// 2.0/sqrt(pi)
    pub static FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;

    /// sqrt(2.0)
    pub static SQRT2: f32 = 1.41421356237309504880168872420969808_f32;

    /// 1.0/sqrt(2.0)
    pub static FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;

    /// Euler's number
    pub static E: f32 = 2.71828182845904523536028747135266250_f32;

    /// log2(e)
    pub static LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;

    /// log10(e)
    pub static LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;

    /// ln(2.0)
    pub static LN_2: f32 = 0.693147180559945309417232121458176568_f32;

    /// ln(10.0)
    pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32;
}

impl Float for f32 {
    #[inline]
    fn nan() -> f32 { NAN }

    #[inline]
    fn infinity() -> f32 { INFINITY }

    #[inline]
    fn neg_infinity() -> f32 { NEG_INFINITY }

    #[inline]
    fn neg_zero() -> f32 { -0.0 }

    /// Returns `true` if the number is NaN.
    #[inline]
    fn is_nan(self) -> bool { self != self }

    /// Returns `true` if the number is infinite.
    #[inline]
    fn is_infinite(self) -> bool {
        self == Float::infinity() || self == Float::neg_infinity()
    }

    /// Returns `true` if the number is neither infinite or NaN.
    #[inline]
    fn is_finite(self) -> bool {
        !(self.is_nan() || self.is_infinite())
    }

    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
    #[inline]
    fn is_normal(self) -> bool {
        self.classify() == FPNormal
    }

    /// Returns the floating point category of the number. If only one property
    /// is going to be tested, it is generally faster to use the specific
    /// predicate instead.
    fn classify(self) -> FPCategory {
        static EXP_MASK: u32 = 0x7f800000;
        static MAN_MASK: u32 = 0x007fffff;

        let bits: u32 = unsafe { mem::transmute(self) };
        match (bits & MAN_MASK, bits & EXP_MASK) {
            (0, 0)        => FPZero,
            (_, 0)        => FPSubnormal,
            (0, EXP_MASK) => FPInfinite,
            (_, EXP_MASK) => FPNaN,
            _             => FPNormal,
        }
    }

    #[inline]
    fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }

    #[inline]
    fn digits(_: Option<f32>) -> uint { DIGITS }

    #[inline]
    fn epsilon() -> f32 { EPSILON }

    #[inline]
    fn min_exp(_: Option<f32>) -> int { MIN_EXP }

    #[inline]
    fn max_exp(_: Option<f32>) -> int { MAX_EXP }

    #[inline]
    fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }

    #[inline]
    fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }

    #[inline]
    fn min_pos_value(_: Option<f32>) -> f32 { MIN_POS_VALUE }

    /// Returns the mantissa, exponent and sign as integers.
    fn integer_decode(self) -> (u64, i16, i8) {
        let bits: u32 = unsafe { mem::transmute(self) };
        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
        let mantissa = if exponent == 0 {
            (bits & 0x7fffff) << 1
        } else {
            (bits & 0x7fffff) | 0x800000
        };
        // Exponent bias + mantissa shift
        exponent -= 127 + 23;
        (mantissa as u64, exponent, sign)
    }

    /// Rounds towards minus infinity.
    #[inline]
    fn floor(self) -> f32 {
        unsafe { intrinsics::floorf32(self) }
    }

    /// Rounds towards plus infinity.
    #[inline]
    fn ceil(self) -> f32 {
        unsafe { intrinsics::ceilf32(self) }
    }

    /// Rounds to nearest integer. Rounds half-way cases away from zero.
    #[inline]
    fn round(self) -> f32 {
        unsafe { intrinsics::roundf32(self) }
    }

    /// Returns the integer part of the number (rounds towards zero).
    #[inline]
    fn trunc(self) -> f32 {
        unsafe { intrinsics::truncf32(self) }
    }

    /// The fractional part of the number, satisfying:
    ///
    /// ```rust
    /// let x = 1.65f32;
    /// assert!(x == x.trunc() + x.fract())
    /// ```
    #[inline]
    fn fract(self) -> f32 { self - self.trunc() }

    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
    /// error. This produces a more accurate result with better performance than
    /// a separate multiplication operation followed by an add.
    #[inline]
    fn mul_add(self, a: f32, b: f32) -> f32 {
        unsafe { intrinsics::fmaf32(self, a, b) }
    }

    /// Returns the reciprocal (multiplicative inverse) of the number.
    #[inline]
    fn recip(self) -> f32 { 1.0 / self }

    fn powi(self, n: i32) -> f32 {
        unsafe { intrinsics::powif32(self, n) }
    }

    #[inline]
    fn powf(self, n: f32) -> f32 {
        unsafe { intrinsics::powf32(self, n) }
    }

    /// sqrt(2.0)
    #[inline]
    fn sqrt2() -> f32 { consts::SQRT2 }

    /// 1.0 / sqrt(2.0)
    #[inline]
    fn frac_1_sqrt2() -> f32 { consts::FRAC_1_SQRT2 }

    #[inline]
    fn sqrt(self) -> f32 {
        unsafe { intrinsics::sqrtf32(self) }
    }

    #[inline]
    fn rsqrt(self) -> f32 { self.sqrt().recip() }

    /// Archimedes' constant
    #[inline]
    fn pi() -> f32 { consts::PI }

    /// 2.0 * pi
    #[inline]
    fn two_pi() -> f32 { consts::PI_2 }

    /// pi / 2.0
    #[inline]
    fn frac_pi_2() -> f32 { consts::FRAC_PI_2 }

    /// pi / 3.0
    #[inline]
    fn frac_pi_3() -> f32 { consts::FRAC_PI_3 }

    /// pi / 4.0
    #[inline]
    fn frac_pi_4() -> f32 { consts::FRAC_PI_4 }

    /// pi / 6.0
    #[inline]
    fn frac_pi_6() -> f32 { consts::FRAC_PI_6 }

    /// pi / 8.0
    #[inline]
    fn frac_pi_8() -> f32 { consts::FRAC_PI_8 }

    /// 1 .0/ pi
    #[inline]
    fn frac_1_pi() -> f32 { consts::FRAC_1_PI }

    /// 2.0 / pi
    #[inline]
    fn frac_2_pi() -> f32 { consts::FRAC_2_PI }

    /// 2.0 / sqrt(pi)
    #[inline]
    fn frac_2_sqrtpi() -> f32 { consts::FRAC_2_SQRTPI }

    /// Euler's number
    #[inline]
    fn e() -> f32 { consts::E }

    /// log2(e)
    #[inline]
    fn log2_e() -> f32 { consts::LOG2_E }

    /// log10(e)
    #[inline]
    fn log10_e() -> f32 { consts::LOG10_E }

    /// ln(2.0)
    #[inline]
    fn ln_2() -> f32 { consts::LN_2 }

    /// ln(10.0)
    #[inline]
    fn ln_10() -> f32 { consts::LN_10 }

    /// Returns the exponential of the number.
    #[inline]
    fn exp(self) -> f32 {
        unsafe { intrinsics::expf32(self) }
    }

    /// Returns 2 raised to the power of the number.
    #[inline]
    fn exp2(self) -> f32 {
        unsafe { intrinsics::exp2f32(self) }
    }

    /// Returns the natural logarithm of the number.
    #[inline]
    fn ln(self) -> f32 {
        unsafe { intrinsics::logf32(self) }
    }

    /// Returns the logarithm of the number with respect to an arbitrary base.
    #[inline]
    fn log(self, base: f32) -> f32 { self.ln() / base.ln() }

    /// Returns the base 2 logarithm of the number.
    #[inline]
    fn log2(self) -> f32 {
        unsafe { intrinsics::log2f32(self) }
    }

    /// Returns the base 10 logarithm of the number.
    #[inline]
    fn log10(self) -> f32 {
        unsafe { intrinsics::log10f32(self) }
    }

    /// Converts to degrees, assuming the number is in radians.
    #[inline]
    fn to_degrees(self) -> f32 { self * (180.0f32 / Float::pi()) }

    /// Converts to radians, assuming the number is in degrees.
    #[inline]
    fn to_radians(self) -> f32 {
        let value: f32 = Float::pi();
        self * (value / 180.0f32)
    }
}
<commit_msg>auto merge of #16356 : ruud-v-a/rust/fix-f32-doc, r=steveklabnik<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Operations and constants for 32-bits floats (`f32` type)

#![doc(primitive = "f32")]
// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
#![allow(type_overflow)]

use intrinsics;
use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
use num::Float;
use option::Option;

pub static RADIX: uint = 2u;

pub static MANTISSA_DIGITS: uint = 24u;
pub static DIGITS: uint = 6u;

pub static EPSILON: f32 = 1.19209290e-07_f32;

/// Smallest finite f32 value
pub static MIN_VALUE: f32 = -3.40282347e+38_f32;
/// Smallest positive, normalized f32 value
pub static MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
/// Largest finite f32 value
pub static MAX_VALUE: f32 = 3.40282347e+38_f32;

pub static MIN_EXP: int = -125;
pub static MAX_EXP: int = 128;

pub static MIN_10_EXP: int = -37;
pub static MAX_10_EXP: int = 38;

pub static NAN: f32 = 0.0_f32/0.0_f32;
pub static INFINITY: f32 = 1.0_f32/0.0_f32;
pub static NEG_INFINITY: f32 = -1.0_f32/0.0_f32;

/// Various useful constants.
pub mod consts {
    // FIXME: replace with mathematical constants from cmath.

    // FIXME(#5527): These constants should be deprecated once associated
    // constants are implemented in favour of referencing the respective members
    // of `Float`.

    /// Archimedes' constant
    pub static PI: f32 = 3.14159265358979323846264338327950288_f32;

    /// pi * 2.0
    pub static PI_2: f32 = 6.28318530717958647692528676655900576_f32;

    /// pi/2.0
    pub static FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;

    /// pi/3.0
    pub static FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;

    /// pi/4.0
    pub static FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;

    /// pi/6.0
    pub static FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;

    /// pi/8.0
    pub static FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;

    /// 1.0/pi
    pub static FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;

    /// 2.0/pi
    pub static FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;

    /// 2.0/sqrt(pi)
    pub static FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;

    /// sqrt(2.0)
    pub static SQRT2: f32 = 1.41421356237309504880168872420969808_f32;

    /// 1.0/sqrt(2.0)
    pub static FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;

    /// Euler's number
    pub static E: f32 = 2.71828182845904523536028747135266250_f32;

    /// log2(e)
    pub static LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;

    /// log10(e)
    pub static LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;

    /// ln(2.0)
    pub static LN_2: f32 = 0.693147180559945309417232121458176568_f32;

    /// ln(10.0)
    pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32;
}

impl Float for f32 {
    #[inline]
    fn nan() -> f32 { NAN }

    #[inline]
    fn infinity() -> f32 { INFINITY }

    #[inline]
    fn neg_infinity() -> f32 { NEG_INFINITY }

    #[inline]
    fn neg_zero() -> f32 { -0.0 }

    /// Returns `true` if the number is NaN.
    #[inline]
    fn is_nan(self) -> bool { self != self }

    /// Returns `true` if the number is infinite.
    #[inline]
    fn is_infinite(self) -> bool {
        self == Float::infinity() || self == Float::neg_infinity()
    }

    /// Returns `true` if the number is neither infinite or NaN.
    #[inline]
    fn is_finite(self) -> bool {
        !(self.is_nan() || self.is_infinite())
    }

    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN.
    #[inline]
    fn is_normal(self) -> bool {
        self.classify() == FPNormal
    }

    /// Returns the floating point category of the number. If only one property
    /// is going to be tested, it is generally faster to use the specific
    /// predicate instead.
    fn classify(self) -> FPCategory {
        static EXP_MASK: u32 = 0x7f800000;
        static MAN_MASK: u32 = 0x007fffff;

        let bits: u32 = unsafe { mem::transmute(self) };
        match (bits & MAN_MASK, bits & EXP_MASK) {
            (0, 0)        => FPZero,
            (_, 0)        => FPSubnormal,
            (0, EXP_MASK) => FPInfinite,
            (_, EXP_MASK) => FPNaN,
            _             => FPNormal,
        }
    }

    #[inline]
    fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }

    #[inline]
    fn digits(_: Option<f32>) -> uint { DIGITS }

    #[inline]
    fn epsilon() -> f32 { EPSILON }

    #[inline]
    fn min_exp(_: Option<f32>) -> int { MIN_EXP }

    #[inline]
    fn max_exp(_: Option<f32>) -> int { MAX_EXP }

    #[inline]
    fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }

    #[inline]
    fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }

    #[inline]
    fn min_pos_value(_: Option<f32>) -> f32 { MIN_POS_VALUE }

    /// Returns the mantissa, exponent and sign as integers.
    fn integer_decode(self) -> (u64, i16, i8) {
        let bits: u32 = unsafe { mem::transmute(self) };
        let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
        let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
        let mantissa = if exponent == 0 {
            (bits & 0x7fffff) << 1
        } else {
            (bits & 0x7fffff) | 0x800000
        };
        // Exponent bias + mantissa shift
        exponent -= 127 + 23;
        (mantissa as u64, exponent, sign)
    }

    /// Rounds towards minus infinity.
    #[inline]
    fn floor(self) -> f32 {
        unsafe { intrinsics::floorf32(self) }
    }

    /// Rounds towards plus infinity.
    #[inline]
    fn ceil(self) -> f32 {
        unsafe { intrinsics::ceilf32(self) }
    }

    /// Rounds to nearest integer. Rounds half-way cases away from zero.
    #[inline]
    fn round(self) -> f32 {
        unsafe { intrinsics::roundf32(self) }
    }

    /// Returns the integer part of the number (rounds towards zero).
    #[inline]
    fn trunc(self) -> f32 {
        unsafe { intrinsics::truncf32(self) }
    }

    /// The fractional part of the number, satisfying:
    ///
    /// ```rust
    /// let x = 1.65f32;
    /// assert!(x == x.trunc() + x.fract())
    /// ```
    #[inline]
    fn fract(self) -> f32 { self - self.trunc() }

    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
    /// error. This produces a more accurate result with better performance than
    /// a separate multiplication operation followed by an add.
    #[inline]
    fn mul_add(self, a: f32, b: f32) -> f32 {
        unsafe { intrinsics::fmaf32(self, a, b) }
    }

    /// Returns the reciprocal (multiplicative inverse) of the number.
    #[inline]
    fn recip(self) -> f32 { 1.0 / self }

    fn powi(self, n: i32) -> f32 {
        unsafe { intrinsics::powif32(self, n) }
    }

    #[inline]
    fn powf(self, n: f32) -> f32 {
        unsafe { intrinsics::powf32(self, n) }
    }

    /// sqrt(2.0)
    #[inline]
    fn sqrt2() -> f32 { consts::SQRT2 }

    /// 1.0 / sqrt(2.0)
    #[inline]
    fn frac_1_sqrt2() -> f32 { consts::FRAC_1_SQRT2 }

    #[inline]
    fn sqrt(self) -> f32 {
        unsafe { intrinsics::sqrtf32(self) }
    }

    #[inline]
    fn rsqrt(self) -> f32 { self.sqrt().recip() }

    /// Archimedes' constant
    #[inline]
    fn pi() -> f32 { consts::PI }

    /// 2.0 * pi
    #[inline]
    fn two_pi() -> f32 { consts::PI_2 }

    /// pi / 2.0
    #[inline]
    fn frac_pi_2() -> f32 { consts::FRAC_PI_2 }

    /// pi / 3.0
    #[inline]
    fn frac_pi_3() -> f32 { consts::FRAC_PI_3 }

    /// pi / 4.0
    #[inline]
    fn frac_pi_4() -> f32 { consts::FRAC_PI_4 }

    /// pi / 6.0
    #[inline]
    fn frac_pi_6() -> f32 { consts::FRAC_PI_6 }

    /// pi / 8.0
    #[inline]
    fn frac_pi_8() -> f32 { consts::FRAC_PI_8 }

    /// 1.0 / pi
    #[inline]
    fn frac_1_pi() -> f32 { consts::FRAC_1_PI }

    /// 2.0 / pi
    #[inline]
    fn frac_2_pi() -> f32 { consts::FRAC_2_PI }

    /// 2.0 / sqrt(pi)
    #[inline]
    fn frac_2_sqrtpi() -> f32 { consts::FRAC_2_SQRTPI }

    /// Euler's number
    #[inline]
    fn e() -> f32 { consts::E }

    /// log2(e)
    #[inline]
    fn log2_e() -> f32 { consts::LOG2_E }

    /// log10(e)
    #[inline]
    fn log10_e() -> f32 { consts::LOG10_E }

    /// ln(2.0)
    #[inline]
    fn ln_2() -> f32 { consts::LN_2 }

    /// ln(10.0)
    #[inline]
    fn ln_10() -> f32 { consts::LN_10 }

    /// Returns the exponential of the number.
    #[inline]
    fn exp(self) -> f32 {
        unsafe { intrinsics::expf32(self) }
    }

    /// Returns 2 raised to the power of the number.
    #[inline]
    fn exp2(self) -> f32 {
        unsafe { intrinsics::exp2f32(self) }
    }

    /// Returns the natural logarithm of the number.
    #[inline]
    fn ln(self) -> f32 {
        unsafe { intrinsics::logf32(self) }
    }

    /// Returns the logarithm of the number with respect to an arbitrary base.
    #[inline]
    fn log(self, base: f32) -> f32 { self.ln() / base.ln() }

    /// Returns the base 2 logarithm of the number.
    #[inline]
    fn log2(self) -> f32 {
        unsafe { intrinsics::log2f32(self) }
    }

    /// Returns the base 10 logarithm of the number.
    #[inline]
    fn log10(self) -> f32 {
        unsafe { intrinsics::log10f32(self) }
    }

    /// Converts to degrees, assuming the number is in radians.
    #[inline]
    fn to_degrees(self) -> f32 { self * (180.0f32 / Float::pi()) }

    /// Converts to radians, assuming the number is in degrees.
    #[inline]
    fn to_radians(self) -> f32 {
        let value: f32 = Float::pi();
        self * (value / 180.0f32)
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to create floating point literals from hexadecimal strings

Once loaded, hexfloat!() is called with a string containing the hexadecimal
floating-point literal, and an optional type (f32 or f64).
If the type is omitted, the literal is treated the same as a normal unsuffixed
literal.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(plugin)]
extern crate hexfloat;

fn main() {
    let val = hexfloat!("0x1.ffffb4", f32);
}
```

# References

* [ExploringBinary: hexadecimal floating point constants]
  (http://www.exploringbinary.com/hexadecimal-floating-point-constants/)

*/

#![crate_name = "hexfloat"]
#![deprecated = "This is now a cargo package located at: \
                 https://github.com/rust-lang/hexfloat"]
#![allow(deprecated)]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(plugin_registrar, managed_boxes)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use rustc::plugin::Registry;

use std::gc::Gc;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("hexfloat", expand_syntax_ext);
}

//Check if the literal is valid (as LLVM expects),
//and return a descriptive error if not.
fn hex_float_lit_err(s: &str) -> Option<(uint, String)> {
    let mut chars = s.chars().peekable();
    let mut i = 0;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    if chars.next() != Some('0') {
        return Some((i, "Expected '0'".to_string()));
    } i+=1;
    if chars.next() != Some('x') {
        return Some((i, "Expected 'x'".to_string()));
    } i+=1;
    let mut d_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; d_len += 1;}
    if chars.next() != Some('.') {
        return Some((i, "Expected '.'".to_string()));
    } i+=1;
    let mut f_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; f_len += 1;}
    if d_len == 0 && f_len == 0 {
        return Some((i, "Expected digits before or after decimal \
                         point".to_string()));
    }
    if chars.next() != Some('p') {
        return Some((i, "Expected 'p'".to_string()));
    } i+=1;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    let mut e_len = 0i;
    for _ in chars.take_while(|c| c.is_digit()) { chars.next(); i+=1; e_len += 1}
    if e_len == 0 {
        return Some((i, "Expected exponent digits".to_string()));
    }
    match chars.next() {
        None => None,
        Some(_) => Some((i, "Expected end of string".to_string()))
    }
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult+'static> {
    let (expr, ty_lit) = parse_tts(cx, tts);

    let ty = match ty_lit {
        None => None,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "f32" => Some(ast::TyF32),
            "f64" => Some(ast::TyF64),
            _ => {
                cx.span_err(span, "invalid floating point type in hexfloat!");
                None
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                s.clone()
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in hexfloat!");
                return base::DummyResult::expr(sp);
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in hexfloat!");
            return base::DummyResult::expr(sp);
        }
    };

    {
        let err = hex_float_lit_err(s.get());
        match err {
            Some((err_pos, err_str)) => {
                let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
                let span = syntax::codemap::mk_sp(pos,pos);
                cx.span_err(span,
                            format!("invalid hex float literal in hexfloat!: \
                                     {}",
                                    err_str).as_slice());
                return base::DummyResult::expr(sp);
            }
            _ => ()
        }
    }

    let lit = match ty {
        None => ast::LitFloatUnsuffixed(s),
        Some (ty) => ast::LitFloat(s, ty)
    };
    MacExpr::new(cx.expr_lit(sp, lit))
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt,
             tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
    let p = &mut cx.new_parser_from_tts(tts);
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>hexfloat: fix fallout from using ptr::P.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to create floating point literals from hexadecimal strings

Once loaded, hexfloat!() is called with a string containing the hexadecimal
floating-point literal, and an optional type (f32 or f64).
If the type is omitted, the literal is treated the same as a normal unsuffixed
literal.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(plugin)]
extern crate hexfloat;

fn main() {
    let val = hexfloat!("0x1.ffffb4", f32);
}
```

# References

* [ExploringBinary: hexadecimal floating point constants]
  (http://www.exploringbinary.com/hexadecimal-floating-point-constants/)

*/

#![crate_name = "hexfloat"]
#![deprecated = "This is now a cargo package located at: \
                 https://github.com/rust-lang/hexfloat"]
#![allow(deprecated)]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(plugin_registrar, managed_boxes)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("hexfloat", expand_syntax_ext);
}

//Check if the literal is valid (as LLVM expects),
//and return a descriptive error if not.
fn hex_float_lit_err(s: &str) -> Option<(uint, String)> {
    let mut chars = s.chars().peekable();
    let mut i = 0;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    if chars.next() != Some('0') {
        return Some((i, "Expected '0'".to_string()));
    } i+=1;
    if chars.next() != Some('x') {
        return Some((i, "Expected 'x'".to_string()));
    } i+=1;
    let mut d_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; d_len += 1;}
    if chars.next() != Some('.') {
        return Some((i, "Expected '.'".to_string()));
    } i+=1;
    let mut f_len = 0i;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; f_len += 1;}
    if d_len == 0 && f_len == 0 {
        return Some((i, "Expected digits before or after decimal \
                         point".to_string()));
    }
    if chars.next() != Some('p') {
        return Some((i, "Expected 'p'".to_string()));
    } i+=1;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    let mut e_len = 0i;
    for _ in chars.take_while(|c| c.is_digit()) { chars.next(); i+=1; e_len += 1}
    if e_len == 0 {
        return Some((i, "Expected exponent digits".to_string()));
    }
    match chars.next() {
        None => None,
        Some(_) => Some((i, "Expected end of string".to_string()))
    }
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult+'static> {
    let (expr, ty_lit) = parse_tts(cx, tts);

    let ty = match ty_lit {
        None => None,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "f32" => Some(ast::TyF32),
            "f64" => Some(ast::TyF64),
            _ => {
                cx.span_err(span, "invalid floating point type in hexfloat!");
                None
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(ref lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                s.clone()
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in hexfloat!");
                return base::DummyResult::expr(sp);
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in hexfloat!");
            return base::DummyResult::expr(sp);
        }
    };

    {
        let err = hex_float_lit_err(s.get());
        match err {
            Some((err_pos, err_str)) => {
                let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
                let span = syntax::codemap::mk_sp(pos,pos);
                cx.span_err(span,
                            format!("invalid hex float literal in hexfloat!: \
                                     {}",
                                    err_str).as_slice());
                return base::DummyResult::expr(sp);
            }
            _ => ()
        }
    }

    let lit = match ty {
        None => ast::LitFloatUnsuffixed(s),
        Some (ty) => ast::LitFloat(s, ty)
    };
    MacExpr::new(cx.expr_lit(sp, lit))
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt,
             tts: &[ast::TokenTree]) -> (P<ast::Expr>, Option<Ident>) {
    let p = &mut cx.new_parser_from_tts(tts);
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<|endoftext|>