stof 0.3.24

Stof is a unified data interface and interchange format for creating, sharing, and manipulating data. Stof removes the fragile and cumbersome parts of combining and using data in applications.
Documentation
//
// Copyright 2024 Formata, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#[test]
fn length() {
    assertEq(4.len(), 4);
    assertEq(Number.len(40), 40);
}

#[test]
fn units() {
    assertEq(3km.units(), 'km');
    assert(123mm.hasUnits());
    assert(!123.hasUnits());
}

#[test]
fn remove_units() {
    let units = 23s;
    assertEq(units.units(), 's');

    units = units.removeUnits();
    assertEq(units.units(), null);
}

#[test]
fn is_angle() {
    assert(15deg.isAngle());
    assert(!12.isAngle());
    assert(44deg.isDegrees());
    assert(!33rad.isDegrees());
    assert(33rad.isRadians());
    assert(!33deg.isRadians());
    assert(45pdeg.isPositiveDegrees());
    assert(!45deg.isPositiveDegrees());
    assert(3prad.isPositiveRadians());
    assert(!3rad.isPositiveRadians());
}

#[test]
fn is_temperature() {
    assert(3C.isTemp());
    assert(!3km.isTemp());
}

#[test]
fn is_length() {
    assert(3km.isLength());
    assert(!3s.isLength());
}

#[test]
fn is_time() {
    assert(3ms.isTime());
    assert(!33F.isTime());
}

#[test]
fn is_mass() {
    assert(3kg.isMass());
    assert(!3.isMass());
}

#[test]
fn sqrt() {
    assertEq(4.sqrt(), 2);
}

#[test]
fn pow() {
    assertEq(2.pow(3), 8);
    assertEq(Number.pow(2, 3), 8);
}

#[test]
fn cbrt() {
    assertEq(8.cbrt(), 2);
}

#[test]
fn abs() {
    assertEq(-3.abs(), 3);
    assertEq(3.abs(), 3);
    assertEq(Number.abs(box(-3434)), 3434);
}

#[test]
fn floor() {
    assertEq(1.45.floor(), 1);
}

#[test]
fn ceil() {
    assertEq(1.45.ceil(), 2);
}

#[test]
fn round() {
    assertEq(12.23456.round(), 12);
    assertEq(12.23456.round(2), 12.23);
    assertEq(12.23456.round(4), 12.2346);
}

#[test]
fn test() {
    assertEq(12.7.trunc(), 12);
}

#[test]
fn fract() {
    assertEq(12.5.fract(), 0.5);
}

#[test]
fn signum() {
    assertEq(23.3.signum(), 1);
    assertEq(-234.3.signum(), -1);
}

#[test]
fn exponent() {
    assertEq(0.exp(), 1); // e^x
}

#[test]
fn exponent_2() {
    assertEq(3.exp2(), 8); // 2^x
}

#[test]
fn ln() {
    assertEq(Number.ln(1), 0);
}

#[test]
fn angles_trig() {
    assertEq(90deg.sin(), 1);
    assertEq(270deg.sin(), -1);
    assertEq(0deg.cos(), 1);
    assertEq(180deg.cos(), -1);
    assertEq(0deg.tan(), 0);
}

#[test]
fn atan2() {
    assertEq(0.atan2(0), 0);
}

#[test]
fn log() {
    assertEq(8.log(2), 3);
}

#[test]
fn indexing() {
    assertEq(34.at(3), 3);
    assertEq(34.at(45), 34);
}

#[test]
fn scientific_notation() {
    let i = -1.21e2;
    assertEq(i, -121);

    i = 12e4;
    assertEq(i, 120000);

    i = 12_000_000e-6;
    assertEq(i, 12);
}

#[test]
fn clear_numbers() {
    let i = +10_000_000;
    assertEq(i, 1e7);

    i = 1.21_32_32e_6;
    assertEq(i, 1213232);
}

#[test]
fn hex_literal() {
    let i = 0xFf;
    assertEq(i, 255);

    i = 0x00_00_AA;
    assertEq(i, 170);
}

#[test]
fn oct_literal() {
    let i = 0o00_55;
    assertEq(i, 45);
}

#[test]
fn bin_literal() {
    let i = 0b0011;
    assertEq(i, 3);

    i = 0b1111;
    assertEq(i, 15);
}

#[test]
fn to_hex_string() {
    let i = 0xAb_04_46_f8_c2;
    let s = i.toHexString();
    assertEq(s, 'AB0446F8C2'); // always caps
}

#[test]
fn to_bin_string() {
    let i = 15.7; // just takes integer values
    assertEq(i.toBinString(), '1111');
}

#[test]
fn to_oct_string() {
    let i = 45;
    assertEq(i.toOctString(), '55');
}

#[test]
fn parse_integer() {
    let i = Number.parse("+10_00");
    assertEq(i, 1000);
}

#[test]
fn parse_float() {
    let i = Number.parse("+12_123e-3");
    assertEq(i, 12.123);
}

#[test]
fn parse_hex() {
    let i = Number.parse("0xff");
    assertEq(i, 255);

    i = Number.parseHex("ff");
    assertEq(i, 255);

    i = Number.parseHex("0xFF");
    assertEq(i, 255);
}

#[test]
fn parse_oct() {
    let i = Number.parse("0o55");
    assertEq(i, 45);

    i = Number.parseOct("55");
    assertEq(i, 45);

    i = Number.parseOct("0o55");
    assertEq(i, 45);
}

#[test]
fn parse_bin() {
    let i = Number.parse("0b111");
    assertEq(i, 7);

    i = Number.parseBin("111");
    assertEq(i, 7);

    i = Number.parseBin("0b111");
    assertEq(i, 7);
}

#[test]
fn parse_together() {
    let i = 1564;
    assertEq(i, Number.parseHex(i.toHexString()));
    assertEq(i, Number.parseOct(i.toOctString()));
    assertEq(i, Number.parseBin(i.toBinString()));
}

bitwise: {
    #[test]
    fn and() {
        let i = 0b0011 & 0b1001;
        assertEq(i, 0b0001);
    }

    #[test]
    fn or() {
        let i = 0b0011 | 0b1001;
        assertEq(i, 0b1011);
    }

    #[test]
    fn xor() {
        let i = 0b0011 ^ 0b1001;
        assertEq(i, 0b1010);
    }

    #[test]
    fn shift_left() {
        let i = 0b0011 << 2;
        assertEq(i, 0b1100);
    }

    #[test]
    fn shift_right() {
        let i = 0b1100 >> 3;
        assertEq(i, 0b0001);
    }

    #[test]
    fn shift_before_bitop() {
        let i =  0b1001 ^ 0b1100 >> 2 & 0b0010 << 2;
        assertEq(i, 0b1000);
    }
}