static int compare_refs(const void *ref1_, const void *ref2_) { const struct ref *ref1 = *(const struct ref **)ref1_; const struct ref *ref2 = *(const struct ref **)ref2_; return ref_compare(ref1, ref2); }
static enum status_code add_ref_to_id_map(struct ref *ref) { void **ref_lists_slot = string_map_put_to(&refs_by_id, ref->id); if (!ref_lists_slot) return SUCCESS; /* First remove the ref from the ID list, to ensure that it is * reinserted at the right position if the type changes. */ { struct ref *list, *prev; for (list = *ref_lists_slot, prev = NULL; list; prev = list, list = list->next) if (list == ref) { if (!prev) *ref_lists_slot = ref->next; else prev->next = ref->next; } ref->next = NULL; } if (*ref_lists_slot == NULL || ref_compare(ref, *ref_lists_slot) <= 0) { ref->next = *ref_lists_slot; *ref_lists_slot = ref; } else { struct ref *list; for (list = *ref_lists_slot; list->next; list = list->next) { if (ref_compare(ref, list->next) <= 0) break; } ref->next = list->next; list->next = ref; } return SUCCESS; }
int is_term_smaller(term_t a, term_t b) { if (a == b) return 0; if (are_both_immed(a, b)) { if (are_both_int(a, b)) return int_value(a) < int_value(b); if (is_int(a)) // !is_int(b) return 1; if (is_nil(a)) // !is_nil(b) return 0; if (is_nil(b)) // !is_nil(a) return 1; if (is_atom(a)) { if (is_int(b)) return 0; else if (is_atom(b)) { uint8_t *print1 = atoms_get(atom_index(a)); uint8_t *print2 = atoms_get(atom_index(b)); int short_len = (print1[0] < print2[0]) ? print1[0] : print2[0]; int d = memcmp(print1+1, print2+1, short_len); if (d == 0) return print1[0] < print2[0]; return d < 0; } else return 1; } else if (is_short_oid(a)) { if (is_int(b) || is_atom(b)) return 0; else if (is_short_oid(b)) return short_oid_id(a) < short_oid_id(b); else return 1; } else if (is_short_pid(a)) { if (is_int(b) || is_atom(b) || is_short_oid(b)) return 0; else { assert(is_short_pid(b)); return short_pid_id(a) < short_pid_id(b); } } } //TODO: comparison of bignum and float: docs mention the // number 9007199254740992.0 and a loss of transitivity if (!is_immed(a) && !is_immed(b) && primary_tag(a) == primary_tag(b)) { if (is_cons(a)) return is_term_smaller_1(a, b); else if (is_tuple(a)) return is_term_smaller_2(a, b); else { assert(is_boxed(a) && is_boxed(b)); uint32_t *adata = peel_boxed(a); uint32_t *bdata = peel_boxed(b); if (boxed_tag(adata) == boxed_tag(bdata) || (is_binary(adata) && is_binary(bdata)) || (is_bignum(adata) && is_bignum(bdata))) { switch(boxed_tag(adata)) { case SUBTAG_POS_BIGNUM: case SUBTAG_NEG_BIGNUM: return bignum_compare((bignum_t *)adata, (bignum_t *)bdata) < 0; case SUBTAG_FUN: return fun_compare((t_fun_t *)adata, (t_fun_t *)bdata) < 0; case SUBTAG_EXPORT: return export_compare((t_export_t *)adata, (t_export_t *)bdata) < 0; case SUBTAG_PID: return pid_compare((t_long_pid_t *)adata, (t_long_pid_t *)bdata) < 0; case SUBTAG_OID: return oid_compare((t_long_oid_t *)adata, (t_long_oid_t *)bdata) < 0; case SUBTAG_REF: return ref_compare((t_long_ref_t *)adata, (t_long_ref_t *)bdata) < 0; case SUBTAG_PROC_BIN: case SUBTAG_HEAP_BIN: case SUBTAG_MATCH_CTX: case SUBTAG_SUB_BIN: return is_term_smaller_3(adata, bdata); default: assert(boxed_tag(adata) == SUBTAG_FLOAT); return float_value(adata) < float_value(bdata); } } } } // Number comparison with (mandatory) coercion // int use_float = (is_boxed(a) && boxed_tag(peel_boxed(a)) == SUBTAG_FLOAT) || (is_boxed(b) && boxed_tag(peel_boxed(b)) == SUBTAG_FLOAT); if (use_float) { if (is_int(a)) // b is always float return (double)int_value(a) < float_value(peel_boxed(b)); else if (is_boxed(a)) { uint32_t *adata = peel_boxed(a); if (is_bignum(adata)) // b is always float return bignum_to_double((bignum_t *)adata) < float_value(peel_boxed(b)); if (boxed_tag(adata) == SUBTAG_FLOAT) { if (is_int(b)) return float_value(adata) < (double)int_value(b); if (is_boxed(b)) { uint32_t *bdata = peel_boxed(b); if (is_bignum(bdata)) return float_value(adata) < bignum_to_double((bignum_t *)bdata); } } } } else // use integer { if (is_int(a)) { if (is_boxed(b)) { uint32_t *bdata = peel_boxed(b); if (is_bignum(bdata)) { bignum_t *bbn = (bignum_t *)bdata; return !bignum_is_neg(bbn); } assert(boxed_tag(bdata) != SUBTAG_FLOAT); } } else if (is_boxed(a)) { uint32_t *adata = peel_boxed(a); if (is_bignum(adata)) { bignum_t *abn = (bignum_t *)adata; if (is_int(b)) return bignum_is_neg(abn); if (is_boxed(b)) { uint32_t *bdata = peel_boxed(b); if (is_bignum(bdata)) return bignum_compare(abn, (bignum_t *)bdata); assert(boxed_tag(bdata) != SUBTAG_FLOAT); } } assert(boxed_tag(adata) != SUBTAG_FLOAT); } } // a and b are quaranteed to have different types // return term_order(a) < term_order(b); }
bool compare(this_type const & rhs) const { return ref_compare(f_, rhs.f_, 0) && l_ == rhs.l_; }