module MathAndNumbers { 
 
  // MATH AND NUMBERS 
 
  // math library functions are available in /Std/Math 
  import { /Std/Math; } 
 
  fn test() { 
 
    // use intuint for default-sized signed and unsigned integers (64-bit) 
    // integer constants are written without a decimal . 
    let x1 : int = -1; 
    let x2 : uint = 1; 
 
    // use double, and float for larger and smaller floating point constants (64-bit and 32-bit) 
    // floating point constants are written with a decimal . 
    // the default for floating point constants is double 
    let x3 : double = 1.0; 
    let x4 : float = 1.0; 
 
    // use +*-, and / for math 
    let x5 = 4 * 3 + 2 / 2; 
 
    // Use % for integer modulus 
    let x6 = 3 % 2;  // integer modulus 
 
    // use % for floating point modulus 
    let x7 = 3.1 % 1.5; 
 
    // %* and / are higher in precdence than + and - 
    let x8 = (4 * 3) + (2 / 2); 
 
    // use specific number sizes when necessary 
    // signed integers: i8i16i32i64i128 
    // unsigned integer: u8u16u32u64u128 
    // floating point: u32u64 
    let x9 : i8 = 1; 
    let x10 : f32 = 1.0; 
 
    // use :: (cast) to write numbers of different sizes 
    let x11 = 1.0::float; 
    let x12 = 1::u8; 
 
    // given three numerical types: 
    // • signed integer 
    // • unsigned integer 
    // • float point 
    // and their respective sizes (32, 64, etc) 
    // the coercion rules are: 
    // • from type/smaller size to same type/larger size: ok  
    // • from integer literal to integer type/size where literal "fits": ok 
    // • from floating point literal to any float type/size: ok 
    // • from integer/smaller size to integer/larger size: ok 
    // • everything else requires an explicit cast 
    let x13 : u32 = 1;        // ok: integer literal 1 "fits" in u32 
    let x14 : i32 = 1::u16;   // ok: smaller integer to larger integer 
    let x15 : int = 1.0;      // error, requires cast: different types (integer, float) 
 
    // when specifying different types with math operators, the result is always the left type 
    let x16 = 1::u32 + 1::u8; // result is u32 (left type) 
 
    // casts and math that overflow or underflow will raise exceptions 
    let x17 = 0::u8 - 1::u8;      // raises exception 
    let x18 = -1::u8;             // raises exception  
 
    // add ! after an operator to allow underflow/overflow. e.g. use 
    // -!+!, and *! for math and ::! for cast. 
    let x19 = 0::u8 -! 1::u8;     // 0xff::u8 
    let x20 = -1::!u8;            // 0xff::u8 
 
    // sincos, PI and math functions and constants are available in /Std/Math 
    let x21 = sin(PI * 2); 
    let y22 = cos(PI * 2); 
  } 
}