138 lines
3.3 KiB
C
138 lines
3.3 KiB
C
#include "types.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
// ----------------- INT -----------------
|
|
static void int_copy(void *dest, const void *src) {
|
|
*(int *) dest = *(const int *) src;
|
|
}
|
|
|
|
static int int_compare(const void *a, const void *b) {
|
|
const int va = *(const int *) a;
|
|
const int vb = *(const int *) b;
|
|
|
|
return (va > vb) - (va < vb);
|
|
}
|
|
|
|
static void int_print(const void *elem) {
|
|
printf("%d", *(const int *) elem);
|
|
}
|
|
|
|
static bool int_parse(void *dest, const char *str) {
|
|
char *end;
|
|
const long val = strtol(str, &end, 10);
|
|
if (end == str || *end != '\0') return false;
|
|
|
|
*(int *) dest = (int) val;
|
|
return true;
|
|
}
|
|
|
|
static TypeInfo INT_TYPE_INFO = {
|
|
.element_size = sizeof(int),
|
|
.copy = int_copy,
|
|
.destroy = NULL,
|
|
.compare = int_compare,
|
|
.print = int_print,
|
|
.parse = int_parse,
|
|
.type_name = "int"
|
|
};
|
|
|
|
const TypeInfo *get_int_type(void) {
|
|
return &INT_TYPE_INFO;
|
|
}
|
|
|
|
// ----------------- DOUBLE -----------------
|
|
static void double_copy(void *dest, const void *src) {
|
|
*(double *) dest = *(const double *) src;
|
|
}
|
|
|
|
static int double_compare(const void *a, const void *b) {
|
|
const double va = *(const double *) a;
|
|
const double vb = *(const double *) b;
|
|
const double error = 1e-12;
|
|
|
|
if (fabs(va - vb) < error) return 0;
|
|
return (va > vb) ? 1 : -1;
|
|
}
|
|
|
|
static void double_print(const void *elem) {
|
|
printf("%.4f", *(const double *) elem);
|
|
}
|
|
|
|
static bool double_parse(void *dest, const char *str) {
|
|
char *end;
|
|
const double val = strtod(str, &end);
|
|
if (end == str || *end != '\0') return false;
|
|
|
|
*(double *) dest = val;
|
|
return true;
|
|
}
|
|
|
|
static TypeInfo DOUBLE_TYPE_INFO = {
|
|
.element_size = sizeof(double),
|
|
.copy = double_copy,
|
|
.destroy = NULL,
|
|
.compare = double_compare,
|
|
.print = double_print,
|
|
.parse = double_parse,
|
|
.type_name = "double"
|
|
};
|
|
|
|
const TypeInfo *get_double_type(void) {
|
|
return &DOUBLE_TYPE_INFO;
|
|
}
|
|
|
|
// ----------------- COMPLEX -----------------
|
|
static void complex_copy(void *dest, const void *src) {
|
|
*(Complex *) dest = *(const Complex *) src;
|
|
}
|
|
|
|
static int complex_compare(const void *a, const void *b) {
|
|
const Complex *ca = (const Complex *) a;
|
|
const Complex *cb = (const Complex *) b;
|
|
const double error = 1e-12;
|
|
|
|
const double ma = ca->re * ca->re + ca->im * ca->im;
|
|
const double mb = cb->re * cb->re + cb->im * cb->im;
|
|
|
|
if (fabs(ma - mb) < error) return 0;
|
|
return (ma > mb) ? 1 : -1;
|
|
}
|
|
|
|
static void complex_print(const void *elem) {
|
|
const Complex *c = (Complex*)elem;
|
|
if (c->im > 0)
|
|
printf("%.4f+%.4fi", c->re, c->im);
|
|
else if (c->im == 0)
|
|
printf("%.4f", c->re);
|
|
else
|
|
printf("%.4f%.4fi", c->re, c->im);
|
|
}
|
|
|
|
static bool complex_parse(void *dest, const char *str) {
|
|
Complex *c = (Complex *)dest;
|
|
// Формат: "re im"
|
|
if (sscanf(str, "%lf %lf", &c->re, &c->im) == 2)
|
|
return true;
|
|
// Попробуем только re
|
|
c->im = 0;
|
|
if (sscanf(str, "%lf", &c->re) == 1)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static TypeInfo COMPLEX_TYPE_INFO = {
|
|
.element_size = sizeof(Complex),
|
|
.copy = complex_copy,
|
|
.destroy = NULL,
|
|
.compare = complex_compare,
|
|
.print = complex_print,
|
|
.parse = complex_parse,
|
|
.type_name = "complex"
|
|
};
|
|
|
|
const TypeInfo *get_complex_type(void) {
|
|
return &COMPLEX_TYPE_INFO;
|
|
}
|