<commit_before>use num::Num;
use point::Point2D;
use size::Size2D;
use cmp::{Eq, Ord};

pub struct Rect<T:Copy Num> {
    origin: Point2D<T>,
    size: Size2D<T>

}

pub pure fn Rect<T:Copy Num>(origin: Point2D<T>, size: Size2D<T>) -> Rect<T> {
    return Rect {
        origin: copy origin,
        size: copy size
    }
}

impl<T: Copy Num Ord> Rect<T> {
    pure fn intersects(other: &Rect<T>) -> bool {
        self.origin.x < other.origin.x.add(&other.size.width) &&
       other.origin.x <  self.origin.x.add(&self.size.width) &&
        self.origin.y < other.origin.y.add(&other.size.height) &&
       other.origin.y <  self.origin.y.add(&self.size.height)
    }
}

impl<T: Copy Num Ord> Rect<T> {
    pure fn intersection(other: &Rect<T>) -> Option<Rect<T>> {
        if !self.intersects(other) { return None }

        Some(Rect(Point2D(max(self.origin.x, other.origin.x),
                            max(self.origin.y, other.origin.y)),
                  Size2D(min(self.origin.x.add(&self.size.width),
                            other.origin.x.add(&other.size.width)),
                         min(self.origin.y.add(&self.size.height),
                            other.origin.y.add(&other.size.height)))
        ))
    }

    pure fn union(other: &Rect<T>) -> Rect<T> {
        Rect {
            origin: Point2D(min(self.origin.x, other.origin.x),
                            min(self.origin.y, other.origin.y)),
            size: Size2D(max(self.origin.x.add(&self.size.width),
                            other.origin.x.add(&other.size.width)),
                         max(self.origin.y.add(&self.size.height),
                            other.origin.y.add(&other.size.height)))
        }
    }
}

impl<T: Copy Num> Rect<T> {
    pure fn translate(other: &Point2D<T>) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x.add(&other.x),
                            self.origin.y.add(&other.y)),
            size: copy self.size
        }
    }
}

impl<T: Copy Num Eq> Rect<T>: Eq {
    pure fn eq(other: &Rect<T>) -> bool {
        self.origin == other.origin && self.size == other.size
    }
    pure fn ne(other: &Rect<T>) -> bool {
        !self.eq(other)
    }
}

pub pure fn min<T: Copy Num Ord>(x: T, y: T) -> T {
    if x <= y { x } else { y }
}

pub pure fn max<T: Copy Num Ord>(x: T, y: T) -> T {
    if x >= y { x } else { y }
}

#[test]
fn test_min_max() {
    assert min(0, 1) == 0;
    assert min(-1.0, 0.0) == -1.0;

    assert max(0, 1) == 1;
    assert max(-1.0, 0.0) == 0.0;
}

#[test]
fn test_translate() {
    let p = Rect(Point2D(0, 0), Size2D(50, 40));
    let pp = p.translate(&Point2D(10,15));

    assert pp.size.width == 50;
    assert pp.size.height == 40;
    assert pp.origin.x == 10;
    assert pp.origin.y == 15;


    let r = Rect(Point2D(-10, -5), Size2D(50, 40));
    let rr = r.translate(&Point2D(0,-10));

    assert rr.size.width == 50;
    assert rr.size.height == 40;
    assert rr.origin.x == -10;
    assert rr.origin.y == -15;
}<commit_msg>Rewrite Rect::union, and add test cases.<commit_after>use num::Num;
use point::Point2D;
use size::Size2D;
use cmp::{Eq, Ord};

pub struct Rect<T:Copy Num> {
    origin: Point2D<T>,
    size: Size2D<T>

}

pub pure fn Rect<T:Copy Num>(origin: Point2D<T>, size: Size2D<T>) -> Rect<T> {
    return Rect {
        origin: copy origin,
        size: copy size
    }
}

impl<T: Copy Num Ord> Rect<T> {
    pure fn intersects(other: &Rect<T>) -> bool {
        self.origin.x < other.origin.x.add(&other.size.width) &&
       other.origin.x <  self.origin.x.add(&self.size.width) &&
        self.origin.y < other.origin.y.add(&other.size.height) &&
       other.origin.y <  self.origin.y.add(&self.size.height)
    }
}

impl<T: Copy Num Ord> Rect<T> {
    pure fn intersection(other: &Rect<T>) -> Option<Rect<T>> {
        if !self.intersects(other) { return None }

        Some(Rect(Point2D(max(self.origin.x, other.origin.x),
                            max(self.origin.y, other.origin.y)),
                  Size2D(min(self.origin.x.add(&self.size.width),
                            other.origin.x.add(&other.size.width)),
                         min(self.origin.y.add(&self.size.height),
                            other.origin.y.add(&other.size.height)))
        ))
    }

    pure fn union(other: &Rect<T>) -> Rect<T> {
        let upper_left = Point2D(min(self.origin.x, other.origin.x),
                                 min(self.origin.y, other.origin.y));
        
        let lower_right = Point2D(max(self.origin.x + self.size.width,
                                      other.origin.x + other.size.width),
                                  max(self.origin.y + self.size.height,
                                      other.origin.y + other.size.height));
        
        Rect {
            origin: upper_left,
            size: Size2D(lower_right.x - upper_left.x, lower_right.y - upper_left.y)
        }
    }
}

impl<T: Copy Num> Rect<T> {
    pure fn translate(other: &Point2D<T>) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x.add(&other.x),
                            self.origin.y.add(&other.y)),
            size: copy self.size
        }
    }
}

impl<T: Copy Num Eq> Rect<T>: Eq {
    pure fn eq(other: &Rect<T>) -> bool {
        self.origin == other.origin && self.size == other.size
    }
    pure fn ne(other: &Rect<T>) -> bool {
        !self.eq(other)
    }
}

pub pure fn min<T: Copy Num Ord>(x: T, y: T) -> T {
    if x <= y { x } else { y }
}

pub pure fn max<T: Copy Num Ord>(x: T, y: T) -> T {
    if x >= y { x } else { y }
}

#[test]
fn test_min_max() {
    assert min(0, 1) == 0;
    assert min(-1.0, 0.0) == -1.0;

    assert max(0, 1) == 1;
    assert max(-1.0, 0.0) == 0.0;
}

#[test]
fn test_translate() {
    let p = Rect(Point2D(0, 0), Size2D(50, 40));
    let pp = p.translate(&Point2D(10,15));

    assert pp.size.width == 50;
    assert pp.size.height == 40;
    assert pp.origin.x == 10;
    assert pp.origin.y == 15;


    let r = Rect(Point2D(-10, -5), Size2D(50, 40));
    let rr = r.translate(&Point2D(0,-10));

    assert rr.size.width == 50;
    assert rr.size.height == 40;
    assert rr.origin.x == -10;
    assert rr.origin.y == -15;
}

#[test]
fn test_union() {
    let p = Rect(Point2D(0,0), Size2D(50, 40));
    let q = Rect(Point2D(20,20), Size2D(5, 5));
    let r = Rect(Point2D(-15, -30), Size2D(200, 15));
    let s = Rect(Point2D(20, -15), Size2D(250, 200));

    let pq = p.union(&q);
    assert pq.origin == Point2D(0, 0);
    assert pq.size == Size2D(50, 40);

    let pr = p.union(&r);
    assert pr.origin == Point2D(-15, -30);
    assert pr.size == Size2D(200, 70);

    let ps = p.union(&s);
    assert ps.origin == Point2D(0, -15);
    assert ps.size == Size2D(270, 200);

}
{'fraction_non_alphanumeric': 0.17640117994100296, 'fraction_numerical': 0.031563421828908554, 'mean_word_length': 1.929157667386609, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2378695', 'n_tokens_mistral': 2609, 'n_tokens_neox': 2484, 'n_words': 526}