git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@570 b9cfdab3-6d41-4d17-bbe4-086880011989
This commit is contained in:
NishiOwO
2025-11-02 19:15:38 +00:00
parent 92db649bda
commit 971ef1b827
15 changed files with 767 additions and 796 deletions

View File

@@ -2,13 +2,33 @@
#include <Mw/Milsko.h>
int main() {
MwWidget w = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT,
MwDEFAULT, 640, 480, MwNtitle, "test", NULL);
MwWidget cpicker;
MwWidget window;
MwWidget button;
MwWidget cpicker = MwColorPicker(w, "cpicker");
void color_callback(MwRGB rgb) {
char hexColor[8];
(void)cpicker;
MwLoop(w);
sprintf(hexColor, "#%02X%02X%02X", rgb.r, rgb.g, rgb.b);
MwSetText(window, MwNbackground, hexColor);
}
void color_picker(MwWidget handle, void* user_data, void* call_data) {
MwWidget cpicker = MwColorPicker(window, "cpicker", color_callback);
MwSetText(cpicker, MwNbackground, MwDefaultBackground);
}
int main() {
window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT,
MwDEFAULT, 640, 480, MwNtitle, "color picker", NULL);
MwSetText(window, MwNbackground, "#000000");
button = MwVaCreateWidget(MwButtonClass, "button", window, 160, 180, 320, 120,
MwNtext, "change window background",
NULL);
MwSetText(button, MwNbackground, MwDefaultBackground);
MwAddUserHandler(button, MwNactivateHandler, color_picker, NULL);
MwLoop(window);
}

View File

@@ -15,21 +15,16 @@ extern "C" {
#endif
typedef struct _MwRGB MwRGB;
typedef struct _MwHSV MwHSV;
struct _MwRGB {
double r;
double g;
double b;
MwU32 r;
MwU32 g;
MwU32 b;
};
struct _MwHSV {
double h; // angle in degrees
double s; // a fraction between 0 and 1
double v; // a fraction between 0 and 1
};
typedef void (*MwColorPickerCallback)(MwRGB rgb);
MWDECL MwWidget MwColorPicker(MwWidget handle, const char* title);
MWDECL MwWidget MwColorPicker(MwWidget handle, const char* title, MwColorPickerCallback cb);
#ifdef __cplusplus
}

View File

@@ -143,6 +143,16 @@ MWDECL void MwGetColor(MwLLColor color, int* red, int* green, int* blue);
*/
MWDECL MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height);
/*!
* @brief Creates a pixmap from raw data
* @param handle Widget
* @param rgb RGBA data
* @param width Width
* @param height Height
* @return Pixmap
*/
MWDECL void MwReloadRaw(MwWidget handle, unsigned char* rgb, int width, int height, MwLLPixmap pixmap);
/*!
* @brief Creates a pixmap from XPM data
* @param handle Widget

View File

@@ -92,6 +92,7 @@ MWDECL void MwLLPolygon(MwLL handle, MwPoint* points, int points_count, MwLLColo
MWDECL void MwLLLine(MwLL handle, MwPoint* points, MwLLColor color);
MWDECL MwLLColor MwLLAllocColor(MwLL handle, int r, int g, int b);
MWDECL void MwLLColorUpdate(MwLL handle, int r, int g, int b, MwLLColor c);
MWDECL void MwLLFreeColor(MwLLColor color);
MWDECL void MwLLGetXYWH(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h);
@@ -105,6 +106,7 @@ MWDECL void MwLLNextEvent(MwLL handle);
MWDECL void MwLLSleep(int ms);
MWDECL MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int height);
MWDECL void MwLLPixmapUpdate(MwLL handle, MwLLPixmap pixmap);
MWDECL void MwLLDestroyPixmap(MwLLPixmap pixmap);
MWDECL void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap);
MWDECL void MwLLSetIcon(MwLL handle, MwLLPixmap pixmap);

View File

@@ -1,7 +1,7 @@
/* $Id$ */
/*!
* @file Mw/LowLevelMath.h
* @brief A few portable functions for supporting simultaneously supporting SIMD and not supporting it
* @brief A few portable functions for simultaneously supporting SIMD and not supporting it
* @warning This is mostly used internally. Anything undocumented, and/or anything with an _ prefix (that doesn't have a corresponding typedef) should be avoided.
*/
@@ -12,70 +12,123 @@
#include <Mw/MachDep.h>
#if defined(__i386__) || defined(__x86_64__) || defined(__WATCOMC__)
#define MwLLMathMMX
#endif
#if !defined(MwLLMathMMX)
// #warning LowLevelMath.h does not yet support this platform
#define MwLLMath_x86
#endif
/*!
* @brief Generic vector type
* @warning Do not try to instantiate this yourself, use the appropriate functions instead.
* @brief SIMD vector
*/
typedef struct _MwLLVec MwLLVec;
typedef union _MwLLVecUnion MwLLVecUnion;
/*!
* @brief SIMD vector type
* @warning Not exhaustive, enums subject to be added later.
*/
enum MwLLVecType {
MwLLVecTypeU8 = 0,
MwLLVecTypeU16,
MwLLVecTypeU32,
MwLLVecTypeU64,
MwLLVecTypeI8,
MwLLVecTypeI16,
MwLLVecTypeI32,
MwLLVecTypeI64,
// clang-format off
struct _MwLLVecDataU8x8 { MwU8 a; MwU8 b; MwU8 c; MwU8 d; MwU8 e; MwU8 f; MwU8 g; MwU8 h;};
struct _MwLLVecDataU16x4 { MwU16 a; MwU16 b; MwU16 c; MwU16 d;};
struct _MwLLVecDataU32x2 { MwU32 a; MwU32 b;};
struct _MwLLVecDataI8x8 { MwI8 a; MwI8 b; MwI8 c; MwI8 d; MwI8 e; MwI8 f; MwI8 g; MwI8 h;};
struct _MwLLVecDataI16x4 { MwI16 a; MwI16 b; MwI16 c; MwI16 d;};
struct _MwLLVecDataI32x2 { MwI32 a; MwI32 b;};
union _MwLLVecUnion {
struct _MwLLVecDataU8x8 u8; struct _MwLLVecDataU16x4 u16; struct _MwLLVecDataU32x2 u32;
struct _MwLLVecDataI8x8 i8; struct _MwLLVecDataI16x4 i16; struct _MwLLVecDataI32x2 i32;
MwU64 all;
};
// clang-format on
enum _MwLLVecType {
_MwLLVecTypeU8x8 = 0,
_MwLLVecTypeU16x4 = 1,
_MwLLVecTypeU32x2 = 2,
_MwLLVecTypeI8x8 = 3,
_MwLLVecTypeI16x4 = 4,
_MwLLVecTypeI32x2 = 5,
_MwLLVecType_Max,
};
struct _MwLLVec {
int ty;
MwLLVecUnion un;
MwLLVecType_Max,
};
MWDECL MwLLVec _MwLLVecCreateGeneric(int ty, ...);
/*!
* @brief Create a SIMD Vector (variadic)
* @warning Prefer using the macro version.
*/
MWDECL MwLLVec* MwLLVaVecCreate(int ty, MwU64 size, ...);
#define MwLLVecU8x8(a, b, c, d, e, f, g, h) _MwLLVecCreateGeneric(_MwLLVecTypeU8x8, a, b, c, d, e, f, g, h)
#define MwLLVecU16x4(a, b, c, d) _MwLLVecCreateGeneric(_MwLLVecTypeU16x4, a, b, c, d)
#define MwLLVecU32x2(a, b) _MwLLVecCreateGeneric(_MwLLVecTypeU32x2, a, b)
#define MwLLVecI8x8(a, b, c, d, e, f, g, h) _MwLLVecCreateGeneric(_MwLLVecTypeI8x8, a, b, c, d, e, f, g, h)
#define MwLLVecI16x4(a, b, c, d) _MwLLVecCreateGeneric(_MwLLVecTypeI16x4, a, b, c, d)
#define MwLLVecI32x2(a, b) _MwLLVecCreateGeneric(_MwLLVecTypeI32x2, a, b)
/*!
* @brief Destroy the given SIMD Vector
*/
MWDECL void MwLLVecDestroy(MwLLVec* vec);
/*!
* @brief index the given SIMD Vector (u8)
*/
MWDECL MwU8 MwLLVecIndexU8(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (u16)
*/
MWDECL MwU16 MwLLVecIndexU16(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (u32)
*/
MWDECL MwU32 MwLLVecIndexU32(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (u64)
*/
MWDECL MwU64 MwLLVecIndexU64(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i8)
*/
MWDECL MwI8 MwLLVecIndexI8(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i16)
*/
MWDECL MwI16 MwLLVecIndexI16(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i32)
*/
MWDECL MwI32 MwLLVecIndexI32(MwLLVec* vec, MwU64 index);
/*!
* @brief index the given SIMD Vector (i64)
*/
MWDECL MwI64 MwLLVecIndexI64(MwLLVec* vec, MwU64 index);
/*!
* @brief SIMD Vector add
*/
MWDECL void MwLLMathAdd(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector multiply
*/
MWDECL void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector subtract
*/
MWDECL void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector reciprocal
*/
MWDECL void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out);
/*!
* @brief SIMD Vector square root
*/
MWDECL void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise and
*/
MWDECL void MwLLMathAnd(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise or
*/
MWDECL void MwLLMathOr(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise shift right
*/
MWDECL void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise shift left
*/
MWDECL void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector bitwise equal
*/
MWDECL void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector greater then
*/
MWDECL void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out);
/*!
* @brief SIMD Vector lesser then
*/
MWDECL void MwLLMathLesserThen(MwLLVec* a, MwLLVec* b, MwLLVec* out);
#endif

View File

@@ -43,8 +43,9 @@ struct _MwLLColor {
};
struct _MwLLPixmap {
int width;
int height;
int width;
int height;
unsigned char* data_scratch_buf;
HBITMAP hBitmap;
HBITMAP hMask;

View File

@@ -233,6 +233,30 @@ MwLLColor MwLLAllocColor(MwLL handle, int r, int g, int b) {
return c;
}
void MwLLColorUpdate(MwLL handle, int r, int g, int b, MwLLColor c) {
XColor xc;
if(handle->red_mask == 0) {
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
xc.red = 256 * r;
xc.green = 256 * g;
xc.blue = 256 * b;
XAllocColor(handle->display, handle->colormap, &xc);
c->pixel = xc.pixel;
} else {
c->pixel = generate_color(handle, r, g, b);
}
c->red = r;
c->green = g;
c->blue = b;
}
void MwLLGetXYWH(MwLL handle, int* x, int* y, unsigned int* w, unsigned int* h) {
Window root;
unsigned int border, depth;
@@ -435,6 +459,9 @@ MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int hei
int evbase, erbase;
XWindowAttributes attr;
r->data_buf = malloc(sizeof(unsigned long) * width * height);
memcpy(r->data_buf, data, sizeof(unsigned long) * width * height);
XGetWindowAttributes(handle->display, handle->window, &attr);
r->depth = attr.depth;
@@ -448,29 +475,38 @@ MwLLPixmap MwLLCreatePixmap(MwLL handle, unsigned char* data, int width, int hei
r->image = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), r->depth, ZPixmap, 0, di, width, height, 32, width * 4);
r->mask = XCreateImage(handle->display, DefaultVisual(handle->display, DefaultScreen(handle->display)), 1, ZPixmap, 0, dm, width, height, 32, width * 4);
for(y = 0; y < height; y++) {
for(x = 0; x < width; x++) {
unsigned char* px = &data[(y * width + x) * 4];
MwLLColor c = MwLLAllocColor(handle, px[0], px[1], px[2]);
unsigned long p = c->pixel;
MwLLPixmapUpdate(handle, r);
return r;
}
MwLLFreeColor(c);
void MwLLPixmapUpdate(MwLL handle, MwLLPixmap r) {
int y, x;
MwLLColor c = NULL;
for(y = 0; y < r->height; y++) {
for(x = 0; x < r->width; x++) {
unsigned char* px = &r->data_buf[(y * r->width + x) * 4];
if(c == NULL) {
c = MwLLAllocColor(handle, px[0], px[1], px[2]);
} else {
MwLLColorUpdate(handle, px[0], px[1], px[2], c);
}
unsigned long p = c->pixel;
XPutPixel(r->image, x, y, p);
*(unsigned long*)(&r->data[(y * width + x) * sizeof(unsigned long)]) = (px[3] << 24) | p;
*(unsigned long*)(&r->data[(y * r->width + x) * sizeof(unsigned long)]) = (px[3] << 24) | p;
}
}
for(y = 0; y < height; y++) {
for(x = 0; x < width; x++) {
if(data[(y * width + x) * 4 + 3]) {
MwLLFreeColor(c);
for(y = 0; y < r->height; y++) {
for(x = 0; x < r->width; x++) {
if(r->data_buf[(y * r->width + x) * 4 + 3]) {
XPutPixel(r->mask, x, y, 1);
} else {
XPutPixel(r->mask, x, y, 0);
}
}
}
return r;
}
void MwLLDestroyPixmap(MwLLPixmap pixmap) {

View File

@@ -55,6 +55,7 @@ struct _MwLLPixmap {
int width;
int height;
unsigned char* data;
unsigned char* data_buf;
int depth;

View File

@@ -4,126 +4,155 @@
#include "color_picker.h"
#include <Mw/LowLevelMath.h>
static MwRGB hsv2rgb(MwHSV in) {
MwRGB out;
static void hsv2rgb(MwU32 h, MwU32 s, MwU32 v, MwU32* r, MwU32* g, MwU32* b) {
uint8_t sextant = h >> 8;
int i = (int)(floor(in.h * 6));
double f = in.h * 6 - i;
double p = in.v * (1 - in.s);
double q = in.v * (1 - f * in.s);
double t = in.v * (1 - (1 - f) * in.s);
#define HSV_SWAPPTR(a, b) \
do { \
MwU32* tmp = a; \
a = b; \
b = tmp; \
} while(0)
switch(i % 6) {
case 0:
out.r = in.v, out.g = t, out.b = p;
break;
case 1:
out.r = q, out.g = in.v, out.b = p;
break;
case 2:
out.r = p, out.g = in.v, out.b = t;
break;
case 3:
out.r = p, out.g = q, out.b = in.v;
break;
case 4:
out.r = t, out.g = p, out.b = in.v;
break;
case 5:
out.r = in.v, out.g = p, out.b = q;
break;
if(sextant & 2) {
HSV_SWAPPTR(r, b);
}
if(sextant & 4) {
HSV_SWAPPTR(g, b);
}
if(!(sextant & 6)) {
if(!(sextant & 1)) {
HSV_SWAPPTR(r, g);
}
} else {
if(sextant & 1) {
HSV_SWAPPTR(r, g);
}
}
return out;
*g = v; // Top level
// Perform actual calculations
/*
* Bottom level: v * (1.0 - s)
* --> (v * (255 - s) + error_corr + 1) / 256
*/
uint16_t ww; // Intermediate result
ww = v * (255 - (s)); // We don't use ~s to prevent size-promotion side effects
ww += 1; // Error correction
ww += ww >> 8; // Error correction
*b = ww >> 8;
MwU32 h_fraction = h & 0xff; // 0...255
MwU32 d; // Intermediate result
if(!(sextant & 1)) {
// *r = ...slope_up...;
d = v * (MwU32)((0xff << 8) - (MwU16)(s * (0xff - h_fraction)));
*r = d >> 16;
} else {
// *r = ...slope_down...;
d = v * (MwU32)((0xff << 8) - (MwU16)(s * h_fraction));
*r = d >> 16;
}
return;
}
static void color_picker_wheel_image_update(color_picker* picker) {
int y, x;
static void color_picker_image_update(color_picker* picker) {
int y, x;
double h;
for(y = 0; y < PICKER_SIZE; y++) {
for(x = 0; x < PICKER_SIZE; x++) {
int i = ((y * PICKER_SIZE) + x) * 4;
int _x = x - (PICKER_SIZE / 2);
int _y = y - (PICKER_SIZE / 2);
double dist = sqrt(_x * _x + _y * _y);
if(picker->dist_table[y][x] == 0) {
picker->dist_table[y][x] = sqrt(_x * _x + _y * _y);
}
double dist = picker->dist_table[y][x];
if(dist >= 180.) {
picker->inner.color_picker_image_data[i] = 0;
picker->inner.color_picker_image_data[i + 1] = 0;
picker->inner.color_picker_image_data[i + 2] = 0;
picker->inner.color_picker_image_data[i + 3] = 0;
picker->color_picker_image_data[i] = 0;
picker->color_picker_image_data[i + 1] = 0;
picker->color_picker_image_data[i + 2] = 0;
picker->color_picker_image_data[i + 3] = 0;
} else {
double xd = (M_PI / 180.) * ((double)_x);
double yd = (M_PI / 180.) * ((double)_y);
float angle = atan2(yd, xd) - M_PI;
float hue = (angle * 180.) / M_PI;
MwHSV hsv_v;
MwRGB color;
if(picker->hue_table[y][x].generated == 0) {
double xd = (M_PI / 180.) * ((double)_x);
double yd = (M_PI / 180.) * ((double)_y);
if(hue < 0.0) {
hue += 360;
float angle = atan2(yd, xd) - M_PI;
float hue = (angle * 180.) / M_PI;
if(hue < 0.0) {
hue += 360;
}
hsv_v.h = (hue) * (HSV_HUE_STEPS / 360.);
hsv_v.s = (dist) * (HSV_SAT_MAX / 180.);
picker->hue_table[y][x] = hsv_v;
picker->hue_table[y][x].generated = 1;
}
hsv_v.h = hue / 360.;
hsv_v.s = (dist / 179.61);
hsv_v.v = picker->inner.value;
color = hsv2rgb(hsv_v);
picker->inner.color_picker_image_data[i] = color.r * 255;
picker->inner.color_picker_image_data[i + 1] = color.g * 255;
picker->inner.color_picker_image_data[i + 2] = color.b * 255;
hsv_v = picker->hue_table[y][x];
hsv_v.v = HSV_VAL_MAX - (picker->value * HSV_VAL_MAX);
picker->inner.color_picker_image_data[i + 3] = 255;
MwRGB color;
hsv2rgb(hsv_v.h, hsv_v.s, hsv_v.v, &color.r, &color.g, &color.b);
picker->color_picker_image_data[i] = color.r;
picker->color_picker_image_data[i + 1] = color.g;
picker->color_picker_image_data[i + 2] = color.b;
picker->color_picker_image_data[i + 3] = 255;
}
}
}
if(picker->inner.color_picker_pixmap != NULL) {
MwLLDestroyPixmap(picker->inner.color_picker_pixmap);
if(picker->color_picker_pixmap == NULL) {
picker->color_picker_pixmap = MwLoadRaw(
picker->parent, picker->color_picker_image_data, PICKER_SIZE, PICKER_SIZE);
} else {
MwReloadRaw(
picker->parent, picker->color_picker_image_data, PICKER_SIZE, PICKER_SIZE, picker->color_picker_pixmap);
}
picker->inner.color_picker_pixmap = MwLoadRaw(
picker->inner.parent, picker->inner.color_picker_image_data, PICKER_SIZE, PICKER_SIZE);
MwVaApply(picker->inner.color_picker_img, MwNpixmap, picker->inner.color_picker_pixmap, NULL);
MwVaApply(picker->color_picker_img, MwNpixmap, picker->color_picker_pixmap, NULL);
}
static void color_picker_click(MwWidget handle, void* user, void* call) {
color_picker* picker = (color_picker*)user;
MwLLMouse* mouse = (MwLLMouse*)call;
char* hexColor;
int i, r, g, b, a;
char* fgColor;
char hexColor[8];
int i;
char fgColor[8];
int fr, fg, fb;
(void)handle;
(void)user;
(void)call;
color_picker_wheel_image_update(picker);
color_picker_image_update(picker);
i = ((mouse->point.y * PICKER_SIZE) + mouse->point.x) * 4;
r = picker->inner.color_picker_image_data[i];
g = picker->inner.color_picker_image_data[i + 1];
b = picker->inner.color_picker_image_data[i + 2];
a = picker->inner.color_picker_image_data[i + 3];
picker->chosen_color.r = picker->color_picker_image_data[i];
picker->chosen_color.g = picker->color_picker_image_data[i + 1];
picker->chosen_color.b = picker->color_picker_image_data[i + 2];
(void)a;
sprintf(hexColor, "#%02X%02X%02X", picker->chosen_color.r, picker->chosen_color.g, picker->chosen_color.b);
hexColor = malloc(8);
fgColor = malloc(8);
sprintf(hexColor, "#%02X%02X%02X", r, g, b);
fr = r > 128 ? 0 : 255;
fg = g > 128 ? 0 : 255;
fb = b > 128 ? 0 : 255;
fr = picker->chosen_color.r > 128 ? 0 : 255;
fg = picker->chosen_color.g > 128 ? 0 : 255;
fb = picker->chosen_color.b > 128 ? 0 : 255;
sprintf(fgColor, "#%02X%02X%02X", fr, fg, fb);
MwSetText(picker->inner.color_display, MwNbackground, hexColor);
MwSetText(picker->inner.color_display_text, MwNforeground, fgColor);
MwSetText(picker->color_display, MwNbackground, hexColor);
MwSetText(picker->color_display_text, MwNforeground, fgColor);
MwSetText(picker->inner.color_display_text, MwNbackground, hexColor);
MwSetText(picker->inner.color_display_text, MwNtext, hexColor);
free(hexColor);
MwSetText(picker->color_display_text, MwNbackground, hexColor);
MwSetText(picker->color_display_text, MwNtext, hexColor);
}
static void color_picker_on_change_value(MwWidget handle, void* user,
void* call) {
@@ -135,48 +164,75 @@ static void color_picker_on_change_value(MwWidget handle, void* user,
(void)diff;
(void)call;
picker->inner.value = 1.0 - ((double)value / 1024.);
picker->value = ((double)value / 1024.);
color_picker_wheel_image_update(picker);
color_picker_image_update(picker);
}
static void color_picker_destroy(color_picker* picker) {
free(picker->color_picker_image_data);
MwLLDestroyPixmap(picker->color_picker_pixmap);
MwDestroyWidget(picker->color_display_text);
MwDestroyWidget(picker->color_display);
MwDestroyWidget(picker->value_slider);
MwDestroyWidget(picker->color_picker_img);
}
static void color_picker_close(MwWidget handle, void* user,
void* call) {
color_picker* picker = (color_picker*)user;
color_picker_destroy(picker);
MwDestroyWidget(handle);
}
static void color_picker_finish(MwWidget handle, void* user,
void* call) {
color_picker* picker = (color_picker*)user;
picker->cb(picker->chosen_color);
color_picker_destroy(picker);
MwDestroyWidget(handle->parent);
}
color_picker* color_picker_setup(MwWidget parent, int w, int h) {
color_picker* picker = malloc(sizeof(color_picker));
memset(picker, 0, sizeof(color_picker));
picker->inner.parent = parent;
picker->parent = parent;
picker->inner.color_picker_img =
MwVaCreateWidget(MwImageClass, "image", picker->inner.parent, IMG_POS_X(w), IMG_POS_Y(h),
picker->color_picker_img =
MwVaCreateWidget(MwImageClass, "image", picker->parent, IMG_POS_X(w), IMG_POS_Y(h),
PICKER_SIZE, PICKER_SIZE, NULL);
picker->inner.color_picker_image_data = malloc(PICKER_SIZE * PICKER_SIZE * 4);
picker->inner.color_display_image_data =
malloc(PICKER_SIZE * COLOR_DISPLAY_HEIGHT * 4);
picker->color_picker_image_data = malloc(PICKER_SIZE * PICKER_SIZE * 4);
picker->inner.color_picker_pixmap = NULL;
picker->inner.color_display_pixmap = NULL;
picker->inner.value = 1;
picker->color_picker_pixmap = NULL;
picker->value = 0;
color_picker_wheel_image_update(picker);
color_picker_image_update(picker);
MwAddUserHandler(picker->inner.color_picker_img, MwNmouseDownHandler,
MwAddUserHandler(picker->color_picker_img, MwNmouseDownHandler,
color_picker_click, picker);
picker->inner.color_display = MwCreateWidget(
MwFrameClass, "colorDisplayFrame", picker->inner.parent, IMG_POS_X(w),
IMG_POS_Y(h) + PICKER_SIZE + MARGIN, PICKER_SIZE, PICKER_SIZE / 16);
MwSetText(picker->inner.color_display, MwNbackground, "#000000");
MwSetInteger(picker->inner.color_display, MwnhasBorder, 1);
MwSetInteger(picker->inner.color_display, MwNinverted, 1);
picker->color_display = MwCreateWidget(
MwFrameClass, "colorDisplayFrame", picker->parent, IMG_POS_X(w),
IMG_POS_Y(h) - (PICKER_SIZE / 16) - MARGIN, PICKER_SIZE, PICKER_SIZE / 16);
MwSetText(picker->color_display, MwNbackground, "#FFFFFF");
MwSetInteger(picker->color_display, MwnhasBorder, 1);
MwSetInteger(picker->color_display, MwNinverted, 1);
picker->inner.color_display_text = MwCreateWidget(
MwLabelClass, "colorDisplayFrameText", picker->inner.color_display,
picker->color_display_text = MwCreateWidget(
MwLabelClass, "colorDisplayFrameText", picker->color_display,
MwDefaultBorderWidth(parent), MwDefaultBorderWidth(parent),
PICKER_SIZE - MwDefaultBorderWidth(parent),
(PICKER_SIZE / 16) - (MwDefaultBorderWidth(parent) * 2));
picker->inner.value_slider = MwVaCreateWidget(
MwScrollBarClass, "value-slider", picker->inner.parent,
MwSetText(picker->color_display_text, MwNtext, "#FFFFFF");
picker->value_slider = MwVaCreateWidget(
MwScrollBarClass, "value-slider", picker->parent,
// x
IMG_POS_X(w) + PICKER_SIZE + MARGIN,
@@ -191,40 +247,42 @@ color_picker* color_picker_setup(MwWidget parent, int w, int h) {
MwNorientation, MwVERTICAL, MwNminValue, 0, MwNmaxValue, 1024, NULL);
MwAddUserHandler(picker->inner.value_slider, MwNchangedHandler,
MwAddUserHandler(picker->value_slider, MwNchangedHandler,
color_picker_on_change_value, picker);
picker->finish = MwCreateWidget(
MwButtonClass, "colorPickerFinish", picker->parent, IMG_POS_X(w),
IMG_POS_Y(h) + PICKER_SIZE + MARGIN, PICKER_SIZE, PICKER_SIZE / 8);
MwSetText(picker->finish, MwNtext, "Select");
MwSetInteger(picker->finish, MwnhasBorder, 1);
MwSetInteger(picker->finish, MwNinverted, 1);
MwAddUserHandler(picker->finish, MwNactivateHandler,
color_picker_finish, picker);
memset(picker->dist_table, 0, sizeof(picker->dist_table));
memset(picker->hue_table, 0, sizeof(picker->hue_table));
return picker;
};
MwWidget MwColorPicker(MwWidget handle, const char* title) {
MwWidget MwColorPicker(MwWidget handle, const char* title, MwColorPickerCallback cb) {
MwPoint p;
color_picker* wheel;
MwWidget window;
int ww, wh;
// remove later
MwLLVec test_1 = MwLLVecU32x2(2, 5);
MwLLVec test_2 = MwLLVecU32x2(2, 12);
MwLLVec test_out = MwLLVecU32x2(0, 0);
MwLLMathAdd(&test_1, &test_2, &test_out);
printf("simd result:\n");
printf("%d + %d = %d\n", test_1.un.u32.a, test_2.un.u32.a, test_out.un.u32.a);
printf("%d + %d = %d\n", test_1.un.u32.b, test_2.un.u32.b, test_out.un.u32.b);
ww = MwGetInteger(handle, MwNwidth);
wh = MwGetInteger(handle, MwNheight);
p.x = p.y = 0;
window = MwVaCreateWidget(MwWindowClass, "main", handle, MwDEFAULT, MwDEFAULT,
ww, wh, MwNtitle, title, NULL);
WIN_SIZE, WIN_SIZE, MwNtitle, title, NULL);
wheel = color_picker_setup(window, ww, wh);
wheel = color_picker_setup(window, WIN_SIZE, WIN_SIZE);
MwAddUserHandler(window, MwNcloseHandler, color_picker_close, wheel);
MwLLDetach(window->lowlevel, &p);
MwLLMakePopup(window->lowlevel, handle->lowlevel);
wheel->cb = cb;
return window;
}

View File

@@ -6,6 +6,7 @@
#include <Mw/ColorPicker.h>
#include <Mw/Milsko.h>
#define WIN_SIZE 512
#define PICKER_SIZE 360
#define IMG_POS_X(w) ((w - PICKER_SIZE) / 2)
#define IMG_POS_Y(h) ((h - PICKER_SIZE) / 2)
@@ -13,31 +14,42 @@
#define MARGIN (PICKER_SIZE / 32)
#define COLOR_DISPLAY_HEIGHT 12
#define HSV_HUE_SEXTANT 256.
#define HSV_HUE_STEPS (6. * HSV_HUE_SEXTANT)
#define HSV_HUE_MIN 0.
#define HSV_HUE_MAX (HSV_HUE_STEPS - 1.)
#define HSV_SAT_MIN 0.
#define HSV_SAT_MAX 255.
#define HSV_VAL_MIN 0.
#define HSV_VAL_MAX 255.
typedef struct _color_picker color_picker;
typedef struct _color_picker_inner color_picker_inner;
typedef struct _color_picker_vtable color_picker_vtable;
typedef struct _MwHSV MwHSV;
struct _color_picker_inner {
MwWidget parent;
MwWidget color_picker_img;
MwWidget value_slider;
MwWidget color_display;
MwWidget color_display_text;
MwLLPixmap color_picker_pixmap;
MwLLPixmap color_display_pixmap;
double value;
unsigned char* color_picker_image_data;
unsigned char* color_display_image_data;
MwPoint point;
};
struct _color_picker_vtable {
void* reserved;
struct _MwHSV {
double h; // angle in degrees
double s; // a fraction between 0 and 1
double v; // a fraction between 0 and 1
MwBool generated;
};
struct _color_picker {
color_picker_inner inner;
color_picker_vtable vtable;
MwWidget parent;
MwWidget color_picker_img;
MwWidget value_slider;
MwWidget color_display;
MwWidget color_display_text;
MwWidget finish;
MwLLPixmap color_picker_pixmap;
double value;
unsigned char* color_picker_image_data;
MwPoint point;
double dist_table[PICKER_SIZE][PICKER_SIZE];
MwHSV hue_table[PICKER_SIZE][PICKER_SIZE];
MwColorPickerCallback cb;
MwRGB chosen_color;
};
color_picker* color_picker_setup(MwWidget parent, int w, int h);

View File

@@ -666,6 +666,34 @@ MwLLPixmap MwLoadRaw(MwWidget handle, unsigned char* rgb, int width, int height)
return px;
}
void MwReloadRaw(MwWidget handle, unsigned char* rgb, int width, int height, MwLLPixmap px) {
int i;
MwLLColor base = handle->bgcolor == NULL ? MwParseColor(handle, MwGetText(handle, MwNbackground)) : handle->bgcolor;
memset(px->data_buf, 0, width * height * 4);
for(i = 0; i < width * height; i++) {
unsigned char* pin = &rgb[i * 4];
unsigned char* pout = &px->data_buf[i * 4];
double a = pin[3];
a /= 255;
if(a != 0) {
pout[0] = pin[0] * a;
pout[1] = pin[1] * a;
pout[2] = pin[2] * a;
pout[0] += base->red * (1 - a);
pout[1] += base->green * (1 - a);
pout[2] += base->blue * (1 - a);
pout[3] = 255;
}
}
if(handle->bgcolor == NULL) MwLLFreeColor(base);
MwLLPixmapUpdate(handle->lowlevel, px);
}
void MwGetColor(MwLLColor color, int* red, int* green, int* blue) {
*red = color->red;
*green = color->green;

View File

@@ -1,424 +1,110 @@
/* $Id$ */
#include <Mw/LowLevelMath.h>
#include "math_internal.h"
static void default_add_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a + b->un.u8.a;
out->un.u8.b = a->un.u8.b + b->un.u8.b;
out->un.u8.c = a->un.u8.c + b->un.u8.c;
out->un.u8.d = a->un.u8.d + b->un.u8.d;
out->un.u8.e = a->un.u8.e + b->un.u8.e;
out->un.u8.f = a->un.u8.f + b->un.u8.f;
out->un.u8.g = a->un.u8.g + b->un.u8.g;
out->un.u8.h = a->un.u8.h + b->un.u8.h;
};
static void default_sub_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a - b->un.u8.a;
out->un.u8.b = a->un.u8.b - b->un.u8.b;
out->un.u8.c = a->un.u8.c - b->un.u8.c;
out->un.u8.d = a->un.u8.d - b->un.u8.d;
out->un.u8.e = a->un.u8.e - b->un.u8.e;
out->un.u8.f = a->un.u8.f - b->un.u8.f;
out->un.u8.g = a->un.u8.g - b->un.u8.g;
out->un.u8.h = a->un.u8.h - b->un.u8.h;
};
static void default_multiply_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a * b->un.u8.a;
out->un.u8.b = a->un.u8.b * b->un.u8.b;
out->un.u8.c = a->un.u8.c * b->un.u8.c;
out->un.u8.d = a->un.u8.d * b->un.u8.d;
out->un.u8.e = a->un.u8.e * b->un.u8.e;
out->un.u8.f = a->un.u8.f * b->un.u8.f;
out->un.u8.g = a->un.u8.g * b->un.u8.g;
out->un.u8.h = a->un.u8.h * b->un.u8.h;
};
static void default_reciprocal_u8(MwLLVec* a, MwLLVec* out) {
out->un.u8.a = pow(a->un.u8.a, -1);
out->un.u8.b = pow(a->un.u8.b, -1);
out->un.u8.c = pow(a->un.u8.c, -1);
out->un.u8.d = pow(a->un.u8.d, -1);
out->un.u8.e = pow(a->un.u8.e, -1);
out->un.u8.f = pow(a->un.u8.f, -1);
out->un.u8.g = pow(a->un.u8.g, -1);
out->un.u8.h = pow(a->un.u8.h, -1);
};
static void default_squareRoot_u8(MwLLVec* a, MwLLVec* out) {
out->un.u8.a = sqrt(a->un.u8.a);
out->un.u8.b = sqrt(a->un.u8.b);
out->un.u8.c = sqrt(a->un.u8.c);
out->un.u8.d = sqrt(a->un.u8.d);
out->un.u8.e = sqrt(a->un.u8.e);
out->un.u8.f = sqrt(a->un.u8.f);
out->un.u8.g = sqrt(a->un.u8.g);
out->un.u8.h = sqrt(a->un.u8.h);
}
static void default_shiftRight_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a >> b->un.u8.a;
out->un.u8.b = a->un.u8.b >> b->un.u8.b;
out->un.u8.c = a->un.u8.c >> b->un.u8.c;
out->un.u8.d = a->un.u8.d >> b->un.u8.d;
out->un.u8.e = a->un.u8.e >> b->un.u8.e;
out->un.u8.f = a->un.u8.f >> b->un.u8.f;
out->un.u8.g = a->un.u8.g >> b->un.u8.g;
out->un.u8.h = a->un.u8.h >> b->un.u8.h;
};
static void default_shiftLeft_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a << b->un.u8.a;
out->un.u8.b = a->un.u8.b << b->un.u8.b;
out->un.u8.c = a->un.u8.c << b->un.u8.c;
out->un.u8.d = a->un.u8.d << b->un.u8.d;
out->un.u8.e = a->un.u8.e << b->un.u8.e;
out->un.u8.f = a->un.u8.f << b->un.u8.f;
out->un.u8.g = a->un.u8.g << b->un.u8.g;
out->un.u8.h = a->un.u8.h << b->un.u8.h;
}
static void default_equal_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a == b->un.u8.a;
out->un.u8.b = a->un.u8.b == b->un.u8.b;
out->un.u8.c = a->un.u8.c == b->un.u8.c;
out->un.u8.d = a->un.u8.d == b->un.u8.d;
out->un.u8.e = a->un.u8.e == b->un.u8.e;
out->un.u8.f = a->un.u8.f == b->un.u8.f;
out->un.u8.g = a->un.u8.g == b->un.u8.g;
out->un.u8.h = a->un.u8.h == b->un.u8.h;
};
static void default_greaterThen_u8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u8.a = a->un.u8.a >= b->un.u8.a;
out->un.u8.b = a->un.u8.b >= b->un.u8.b;
out->un.u8.c = a->un.u8.c >= b->un.u8.c;
out->un.u8.d = a->un.u8.d >= b->un.u8.d;
out->un.u8.e = a->un.u8.e >= b->un.u8.e;
out->un.u8.f = a->un.u8.f >= b->un.u8.f;
out->un.u8.g = a->un.u8.g >= b->un.u8.g;
out->un.u8.h = a->un.u8.h >= b->un.u8.h;
};
static MwLLMathVTable table_u8 = {
default_add_u8,
default_multiply_u8,
default_sub_u8,
default_reciprocal_u8,
default_squareRoot_u8,
NULL,
NULL,
default_shiftRight_u8,
default_shiftLeft_u8,
default_equal_u8,
default_greaterThen_u8,
NULL};
static void default_add_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a + b->un.u16.a;
out->un.u16.b = a->un.u16.b + b->un.u16.b;
out->un.u16.c = a->un.u16.c + b->un.u16.c;
out->un.u16.d = a->un.u16.d + b->un.u16.d;
}
static void default_sub_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a - b->un.u16.a;
out->un.u16.b = a->un.u16.b - b->un.u16.b;
out->un.u16.c = a->un.u16.c - b->un.u16.c;
out->un.u16.d = a->un.u16.d - b->un.u16.d;
}
static void default_multiply_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a * b->un.u16.a;
out->un.u16.b = a->un.u16.b * b->un.u16.b;
out->un.u16.c = a->un.u16.c * b->un.u16.c;
out->un.u16.d = a->un.u16.d * b->un.u16.d;
}
static void default_reciprocal_u16(MwLLVec* a, MwLLVec* out) {
out->un.u16.a = pow(a->un.u16.a, -1);
out->un.u16.b = pow(a->un.u16.b, -1);
out->un.u16.c = pow(a->un.u16.c, -1);
out->un.u16.d = pow(a->un.u16.d, -1);
};
static void default_squareRoot_u16(MwLLVec* a, MwLLVec* out) {
out->un.u16.a = sqrt(a->un.u16.a);
out->un.u16.b = sqrt(a->un.u16.b);
out->un.u16.c = sqrt(a->un.u16.c);
out->un.u16.d = sqrt(a->un.u16.d);
};
#define MAKE_DEFAULT_TABLE(suffix, ty) \
static void add_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] + ((ty*)b->buffer)[i]; \
} \
}; \
static void sub_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] - ((ty*)b->buffer)[i]; \
} \
}; \
static void multiply_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] * ((ty*)b->buffer)[i]; \
} \
}; \
static void reciprocal_##suffix(MwLLVec* a, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = pow(((ty*)a->buffer)[i], -1); \
} \
}; \
static void squareRoot_##suffix(MwLLVec* a, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = sqrt(((ty*)a->buffer)[i]); \
} \
} \
static void shiftRight_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] >> ((ty*)b->buffer)[i]; \
} \
}; \
static void shiftLeft_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] << ((ty*)b->buffer)[i]; \
} \
} \
static void equal_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] == ((ty*)b->buffer)[i]; \
} \
}; \
static void greaterThen_##suffix(MwLLVec* a, MwLLVec* b, MwLLVec* out) { \
int i = 0; \
for(; i < a->size; i++) { \
((ty*)out->buffer)[i] = ((ty*)a->buffer)[i] >= ((ty*)b->buffer)[i]; \
} \
}; \
static MwLLMathVTable table_##suffix = {add_##suffix, multiply_##suffix, sub_##suffix, reciprocal_##suffix, squareRoot_##suffix, NULL, NULL, shiftRight_##suffix, shiftLeft_##suffix, equal_##suffix, greaterThen_##suffix, NULL};
static void default_shiftRight_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a >> b->un.u16.a;
out->un.u16.b = a->un.u16.b >> b->un.u16.b;
out->un.u16.c = a->un.u16.c >> b->un.u16.c;
out->un.u16.d = a->un.u16.d >> b->un.u16.d;
};
static void default_shiftLeft_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a << b->un.u16.a;
out->un.u16.b = a->un.u16.b << b->un.u16.b;
out->un.u16.c = a->un.u16.c << b->un.u16.c;
out->un.u16.d = a->un.u16.d << b->un.u16.d;
}
static void default_equal_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a == b->un.u16.a;
out->un.u16.b = a->un.u16.b == b->un.u16.b;
out->un.u16.c = a->un.u16.c == b->un.u16.c;
out->un.u16.d = a->un.u16.d == b->un.u16.d;
}
static void default_greaterThen_u16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u16.a = a->un.u16.a >= b->un.u16.a;
out->un.u16.b = a->un.u16.b >= b->un.u16.b;
out->un.u16.c = a->un.u16.c >= b->un.u16.c;
out->un.u16.d = a->un.u16.d >= b->un.u16.d;
}
static MwLLMathVTable table_u16 = {
default_add_u16,
default_multiply_u16,
default_sub_u16,
default_reciprocal_u16,
default_squareRoot_u16,
NULL,
NULL,
default_shiftRight_u16,
default_shiftLeft_u16,
default_equal_u16,
default_greaterThen_u16,
NULL};
MAKE_DEFAULT_TABLE(u8, MwU8);
MAKE_DEFAULT_TABLE(u16, MwU16);
MAKE_DEFAULT_TABLE(u32, MwU32);
MAKE_DEFAULT_TABLE(u64, MwU64);
MAKE_DEFAULT_TABLE(i8, MwI8);
MAKE_DEFAULT_TABLE(i16, MwI16);
MAKE_DEFAULT_TABLE(i32, MwI32);
MAKE_DEFAULT_TABLE(i64, MwI64);
static void default_add_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u32.a = a->un.u32.a + b->un.u32.a;
out->un.u32.b = a->un.u32.b + b->un.u32.b;
}
static void default_sub_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u32.a = a->un.u32.a - b->un.u32.a;
out->un.u32.b = a->un.u32.b - b->un.u32.b;
}
static void default_multiply_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u32.a = a->un.u32.a * b->un.u32.a;
out->un.u32.b = a->un.u32.b * b->un.u32.b;
}
static void default_reciprocal_u32(MwLLVec* a, MwLLVec* out) {
out->un.u32.a = pow(a->un.u32.a, -1);
out->un.u32.b = pow(a->un.u32.b, -1);
static MwLLMathVTable* defaultMultiTable[MwLLVecType_Max] = {
&table_u8, /*MwLLVecTypeU8*/
&table_u16, /*MwLLVecTypeU16*/
&table_u32, /*MwLLVecTypeU32*/
&table_u64, /*MwLLVecTypeU64*/
&table_i8, /*MwLLVecTypeI8*/
&table_i16, /*MwLLVecTypeI16*/
&table_i32, /*MwLLVecTypeI32*/
&table_i64, /*MwLLVecTypeI64*/
};
static void default_squareRoot_u32(MwLLVec* a, MwLLVec* out) {
out->un.u32.a = sqrt(a->un.u32.a);
out->un.u32.b = sqrt(a->un.u32.b);
};
static void default_shiftRight_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u32.a = a->un.u32.a >> b->un.u32.a;
out->un.u32.b = a->un.u32.b >> b->un.u32.b;
};
static void default_shiftLeft_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u32.a = a->un.u32.a << b->un.u32.a;
out->un.u32.b = a->un.u32.b << b->un.u32.b;
}
static void default_equal_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u32.a = a->un.u32.a == b->un.u32.a;
out->un.u32.b = a->un.u32.b == b->un.u32.b;
}
static void default_greaterThen_u32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.u32.a = a->un.u32.a >= b->un.u32.a;
out->un.u32.b = a->un.u32.b >= b->un.u32.b;
}
static MwLLMathVTable table_u32 = {
default_add_u32,
default_multiply_u32,
default_sub_u32,
default_reciprocal_u32,
default_squareRoot_u32,
NULL,
NULL,
default_shiftRight_u32,
default_shiftLeft_u32,
default_equal_u32,
default_greaterThen_u32,
NULL};
static void default_add_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a + b->un.i8.a;
out->un.i8.b = a->un.i8.b + b->un.i8.b;
out->un.i8.c = a->un.i8.c + b->un.i8.c;
out->un.i8.d = a->un.i8.d + b->un.i8.d;
out->un.i8.e = a->un.i8.e + b->un.i8.e;
out->un.i8.f = a->un.i8.f + b->un.i8.f;
out->un.i8.g = a->un.i8.g + b->un.i8.g;
out->un.i8.h = a->un.i8.h + b->un.i8.h;
};
static void default_sub_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a - b->un.i8.a;
out->un.i8.b = a->un.i8.b - b->un.i8.b;
out->un.i8.c = a->un.i8.c - b->un.i8.c;
out->un.i8.d = a->un.i8.d - b->un.i8.d;
out->un.i8.e = a->un.i8.e - b->un.i8.e;
out->un.i8.f = a->un.i8.f - b->un.i8.f;
out->un.i8.g = a->un.i8.g - b->un.i8.g;
out->un.i8.h = a->un.i8.h - b->un.i8.h;
};
static void default_multiply_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a * b->un.i8.a;
out->un.i8.b = a->un.i8.b * b->un.i8.b;
out->un.i8.c = a->un.i8.c * b->un.i8.c;
out->un.i8.d = a->un.i8.d * b->un.i8.d;
out->un.i8.e = a->un.i8.e * b->un.i8.e;
out->un.i8.f = a->un.i8.f * b->un.i8.f;
out->un.i8.g = a->un.i8.g * b->un.i8.g;
out->un.i8.h = a->un.i8.h * b->un.i8.h;
};
static void default_reciprocal_i8(MwLLVec* a, MwLLVec* out) {
out->un.i8.a = pow(a->un.i8.a, -1);
out->un.i8.b = pow(a->un.i8.b, -1);
out->un.i8.c = pow(a->un.i8.c, -1);
out->un.i8.d = pow(a->un.i8.d, -1);
out->un.i8.e = pow(a->un.i8.e, -1);
out->un.i8.f = pow(a->un.i8.f, -1);
out->un.i8.g = pow(a->un.i8.g, -1);
out->un.i8.h = pow(a->un.i8.h, -1);
};
static void default_squareRoot_i8(MwLLVec* a, MwLLVec* out) {
out->un.i8.a = sqrt(a->un.i8.a);
out->un.i8.b = sqrt(a->un.i8.b);
out->un.i8.c = sqrt(a->un.i8.c);
out->un.i8.d = sqrt(a->un.i8.d);
out->un.i8.e = sqrt(a->un.i8.e);
out->un.i8.f = sqrt(a->un.i8.f);
out->un.i8.g = sqrt(a->un.i8.g);
out->un.i8.h = sqrt(a->un.i8.h);
}
static void default_equal_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a == b->un.i8.a;
out->un.i8.b = a->un.i8.b == b->un.i8.b;
out->un.i8.c = a->un.i8.c == b->un.i8.c;
out->un.i8.d = a->un.i8.d == b->un.i8.d;
out->un.i8.e = a->un.i8.e == b->un.i8.e;
out->un.i8.f = a->un.i8.f == b->un.i8.f;
out->un.i8.g = a->un.i8.g == b->un.i8.g;
out->un.i8.h = a->un.i8.h == b->un.i8.h;
};
static void default_greaterThen_i8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i8.a = a->un.i8.a >= b->un.i8.a;
out->un.i8.b = a->un.i8.b >= b->un.i8.b;
out->un.i8.c = a->un.i8.c >= b->un.i8.c;
out->un.i8.d = a->un.i8.d >= b->un.i8.d;
out->un.i8.e = a->un.i8.e >= b->un.i8.e;
out->un.i8.f = a->un.i8.f >= b->un.i8.f;
out->un.i8.g = a->un.i8.g >= b->un.i8.g;
out->un.i8.h = a->un.i8.h >= b->un.i8.h;
};
static MwLLMathVTable table_i8 = {
default_add_i8,
default_multiply_i8,
default_sub_i8,
default_reciprocal_i8,
default_squareRoot_i8,
NULL,
NULL,
default_shiftRight_u8,
default_shiftLeft_u8,
default_equal_i8,
default_greaterThen_i8,
NULL};
static void default_add_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a + b->un.i16.a;
out->un.i16.b = a->un.i16.b + b->un.i16.b;
out->un.i16.c = a->un.i16.c + b->un.i16.c;
out->un.i16.d = a->un.i16.d + b->un.i16.d;
}
static void default_sub_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a - b->un.i16.a;
out->un.i16.b = a->un.i16.b - b->un.i16.b;
out->un.i16.c = a->un.i16.c - b->un.i16.c;
out->un.i16.d = a->un.i16.d - b->un.i16.d;
}
static void default_multiply_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a * b->un.i16.a;
out->un.i16.b = a->un.i16.b * b->un.i16.b;
out->un.i16.c = a->un.i16.c * b->un.i16.c;
out->un.i16.d = a->un.i16.d * b->un.i16.d;
}
static void default_reciprocal_i16(MwLLVec* a, MwLLVec* out) {
out->un.i16.a = pow(a->un.i16.a, -1);
out->un.i16.b = pow(a->un.i16.b, -1);
out->un.i16.c = pow(a->un.i16.c, -1);
out->un.i16.d = pow(a->un.i16.d, -1);
};
static void default_squareRoot_i16(MwLLVec* a, MwLLVec* out) {
out->un.i16.a = sqrt(a->un.i16.a);
out->un.i16.b = sqrt(a->un.i16.b);
out->un.i16.c = sqrt(a->un.i16.c);
out->un.i16.d = sqrt(a->un.i16.d);
};
static void default_equal_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a == b->un.i16.a;
out->un.i16.b = a->un.i16.b == b->un.i16.b;
out->un.i16.c = a->un.i16.c == b->un.i16.c;
out->un.i16.d = a->un.i16.d == b->un.i16.d;
}
static void default_greaterThen_i16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i16.a = a->un.i16.a >= b->un.i16.a;
out->un.i16.b = a->un.i16.b >= b->un.i16.b;
out->un.i16.c = a->un.i16.c >= b->un.i16.c;
out->un.i16.d = a->un.i16.d >= b->un.i16.d;
}
static MwLLMathVTable table_i16 = {
default_add_i16,
default_multiply_i16,
default_sub_i16,
default_reciprocal_i16,
default_squareRoot_i16,
NULL,
NULL,
default_shiftRight_u16,
default_shiftLeft_u16,
default_equal_i16,
default_greaterThen_i16,
NULL};
static void default_add_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a + b->un.i32.a;
out->un.i32.b = a->un.i32.b + b->un.i32.b;
}
static void default_sub_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a - b->un.i32.a;
out->un.i32.b = a->un.i32.b - b->un.i32.b;
}
static void default_multiply_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a * b->un.i32.a;
out->un.i32.b = a->un.i32.b * b->un.i32.b;
}
static void default_reciprocal_i32(MwLLVec* a, MwLLVec* out) {
out->un.i32.a = pow(a->un.i32.a, -1);
out->un.i32.b = pow(a->un.i32.b, -1);
};
static void default_squareRoot_i32(MwLLVec* a, MwLLVec* out) {
out->un.i32.a = sqrt(a->un.i32.a);
out->un.i32.b = sqrt(a->un.i32.b);
};
static void default_equal_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a == b->un.i32.a;
out->un.i32.b = a->un.i32.b == b->un.i32.b;
}
static void default_greaterThen_i32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.i32.a = a->un.i32.a >= b->un.i32.a;
out->un.i32.b = a->un.i32.b >= b->un.i32.b;
}
static MwLLMathVTable table_i32 = {
default_add_i32,
default_multiply_i32,
default_sub_i32,
default_reciprocal_i32,
default_squareRoot_i32,
NULL,
NULL,
default_shiftRight_u32,
default_shiftLeft_u32,
default_equal_i32,
default_greaterThen_i32,
NULL};
static MwLLMathVTable* defaultMultiTable[_MwLLVecType_Max] = {
&table_u8, // _MwLLVecTypeU8x8
&table_u16, // _MwLLVecTypeU16x4
&table_u32, // _MwLLVecTypeU32x2
&table_i8, // _MwLLVecTypeI8x8
&table_i16, // _MwLLVecTypeI16x4
&table_i32, // _MwLLVecTypeI32x2
};
MwLLMathVTable** default_multi_table(void) {
return defaultMultiTable;
void default_apply(MwLLVec* v) {
switch(v->ty) {
case MwLLVecTypeU8:
v->vtable = table_u8;
break;
case MwLLVecTypeU16:
v->vtable = table_u16;
break;
case MwLLVecTypeU32:
v->vtable = table_u32;
break;
case MwLLVecTypeU64:
v->vtable = table_u64;
break;
case MwLLVecTypeI8:
v->vtable = table_i8;
break;
case MwLLVecTypeI16:
v->vtable = table_i16;
break;
case MwLLVecTypeI32:
v->vtable = table_i32;
break;
case MwLLVecTypeI64:
v->vtable = table_i64;
break;
case MwLLVecType_Max:
break;
}
}

View File

@@ -3,45 +3,17 @@
#include "math_internal.h"
MwLLVec _MwLLVecCreateGeneric(int ty, ...) {
MwLLVecUnion un;
MwLLVec vec;
va_list va;
#if defined(MwLLMath_x86)
struct x86Features {
MwBool mmx;
MwBool sse2;
};
va_start(va, ty);
// clang-format off
#define _A_B(ty) un.ty.a = va_arg(va, int); un.ty.b = va_arg(va, int);
#define _C_D(ty) un.ty.c = va_arg(va, int); un.ty.d = va_arg(va, int);
#define _E_F(ty) un.ty.e = va_arg(va, int); un.ty.f = va_arg(va, int);
#define _G_H(ty) un.ty.g = va_arg(va, int); un.ty.h = va_arg(va, int);
switch(ty) {
case _MwLLVecTypeU8x8: _A_B(u8); _C_D(u8); _E_F(u8); _G_H(u8); break;
case _MwLLVecTypeU16x4: _A_B(u16); _C_D(u16); break;
case _MwLLVecTypeU32x2: _A_B(u32); break;
case _MwLLVecTypeI8x8: _A_B(i8); _C_D(i8); _E_F(i8); _G_H(i8); break;
case _MwLLVecTypeI16x4: _A_B(i16); _C_D(i16); break;
case _MwLLVecTypeI32x2: _A_B(i32); break;
case _MwLLVecType_Max: break;
}
#undef _A_B
#undef _C_D
#undef _E_F
#undef _G_H
// clang-format on
va_end(va);
vec.ty = ty;
vec.un = un;
return vec;
}
#if defined(MwLLMathMMX)
static MwU32 getCPUFeatures(void) {
MwU32 _eax = 1;
MwU32 _edx;
static struct x86Features
getCPUFeatures(void) {
MwU32 _eax = 1;
MwU32 _edx;
struct x86Features features;
#ifdef __WATCOMC__
__asm {
@@ -56,87 +28,159 @@ static MwU32 getCPUFeatures(void) {
: "a"(1) : "ebx", "ecx");
#endif
return _edx;
if(_edx & FEATX86_MMX) {
features.mmx = MwTRUE;
}
if(_edx & FEATX86_SSE2) {
features.sse2 = MwTRUE;
}
return features;
}
#endif
static MwLLMathVTable** mwLLMultiTable;
static MwLLMathVTable* multiTableSetupAndGet(int ty);
static MwLLMathVTable* multiTableGet(int ty);
static MwLLMathVTable* (*mwLLmathFunc)(int ty) = multiTableSetupAndGet;
static MwLLMathVTable* getMultiTable(int ty) {
return mwLLmathFunc(ty);
static int round_multiple(int num, int mul) {
return ((num + mul - 1) / mul) * mul;
}
static MwLLMathVTable* multiTableSetupAndGet(int ty) {
#if defined(MwLLMathMMX)
MwU32 features;
#endif
MwLLVec* MwLLVaVecCreate(int ty, MwU64 size, ...) {
struct x86Features features = getCPUFeatures();
MwLLVec* vec = malloc(sizeof(MwLLVec));
va_list va;
int i = 0;
int size_rounded = size;
mwLLMultiTable = default_multi_table();
memset(vec, 0, sizeof(MwLLVec));
#if defined(MwLLMathMMX)
features = getCPUFeatures();
printf("Avaliable x86_64 Features:\n");
printf("\tMMX: %s\n", features & FEATX86_MMX ? "true" : "false");
printf("\tSSE: %s\n", features & FEATX86_SSE ? "true" : "false");
printf("\tSSE2: %s\n", features & FEATX86_SSE2 ? "true" : "false");
vec->size = size;
if(features & FEATX86_MMX) {
mmx_apply(mwLLMultiTable);
#ifdef MwLLMath_x86
if(features.mmx) {
size_rounded = round_multiple(size, 64);
}
#endif
mwLLmathFunc = multiTableGet;
va_start(va, size);
return mwLLMultiTable[ty];
}
static MwLLMathVTable* multiTableGet(int ty) {
return mwLLMultiTable[ty];
switch(ty) {
case MwLLVecTypeU8:
case MwLLVecTypeI8:
vec->buffer = malloc(size_rounded * sizeof(MwU8));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU8*)vec->buffer)[i] = va_arg(va, int);
}
break;
case MwLLVecTypeU16:
case MwLLVecTypeI16:
vec->buffer = malloc(size_rounded * sizeof(MwU16));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU16*)vec->buffer)[i] = va_arg(va, int);
}
break;
case MwLLVecTypeU32:
case MwLLVecTypeI32:
vec->buffer = malloc(size_rounded * sizeof(MwU32));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU32*)vec->buffer)[i] = va_arg(va, int);
}
break;
case MwLLVecTypeU64:
case MwLLVecTypeI64:
vec->buffer = malloc(size_rounded * sizeof(MwU64));
memset(vec->buffer, 0, size_rounded);
for(; i < size; i++) {
((MwU64*)vec->buffer)[i] = va_arg(va, int);
}
break;
default:
printf("Unknown MwLLVecType %d\n", ty);
break;
}
va_end(va);
default_apply(vec);
#ifdef MwLLMath_x86
if(features.mmx) {
mmx_apply(vec);
}
#endif
return vec;
}
// TODO: Flag for telling debug builds so we can selectively take this out
#define dbg_assert(a) assert(a)
void MwLLMathAdd(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->Add(a, b, out);
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.add(a, b, out);
}
void MwLLMathSub(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->Sub(a, b, out);
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.sub(a, b, out);
}
void MwLLMathMultiply(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->Multiply(a, b, out);
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.multiply(a, b, out);
}
void MwLLMathReciprocal(MwLLVec* a, MwLLVec* out) {
assert(a->ty == out->ty);
getMultiTable(a->ty)->Reciprocal(a, out);
dbg_assert(a->size == out->size);
a->vtable.reciprocal(a, out);
}
void MwLLMathSquareRoot(MwLLVec* a, MwLLVec* out) {
assert(a->ty == out->ty);
getMultiTable(a->ty)->SquareRoot(a, out);
dbg_assert(a->size == out->size);
a->vtable.squareRoot(a, out);
}
void MwLLMathShiftRight(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->ShiftRight(a, b, out);
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.shiftRight(a, b, out);
}
void MwLLMathShiftLeft(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->ShiftLeft(a, b, out);
dbg_assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
a->vtable.shiftLeft(a, b, out);
}
void MwLLMathEqual(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->Equal(a, b, out);
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
}
void MwLLMathGreaterThen(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
assert(a->ty == b->ty && a->ty == out->ty && b->ty == out->ty);
getMultiTable(a->ty)->GreaterThen(a, b, out);
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.shiftRight(a, b, out);
}
void MwLLMathAnd(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.all = a->un.all & b->un.all;
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.and (a, b, out);
}
void MwLLMathOr(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
out->un.all = a->un.all | b->un.all;
dbg_assert(a->size == b->size && a->size == out->size && b->size && out->size);
a->vtable.or (a, b, out);
}
MWDECL MwU8 MwLLVecIndexU8(MwLLVec* vec, MwU64 index) {
return ((MwU8*)vec->buffer)[index];
};
MWDECL MwU16 MwLLVecIndexU16(MwLLVec* vec, MwU64 index) {
return ((MwU16*)vec->buffer)[index];
};
MWDECL MwU32 MwLLVecIndexU32(MwLLVec* vec, MwU64 index) {
return ((MwU32*)vec->buffer)[index];
};
MWDECL MwU64 MwLLVecIndexU64(MwLLVec* vec, MwU64 index) {
return ((MwU64*)vec->buffer)[index];
};
MWDECL MwI8 MwLLVecIndexI8(MwLLVec* vec, MwU64 index) {
return ((MwI8*)vec->buffer)[index];
};
MWDECL MwI16 MwLLVecIndexI16(MwLLVec* vec, MwU64 index) {
return ((MwI16*)vec->buffer)[index];
};
MWDECL MwI32 MwLLVecIndexI32(MwLLVec* vec, MwU64 index) {
return ((MwI32*)vec->buffer)[index];
};
MWDECL MwI64 MwLLVecIndexI64(MwLLVec* vec, MwU64 index) {
return ((MwI64*)vec->buffer)[index];
};

View File

@@ -6,31 +6,38 @@
#include <Mw/BaseTypes.h>
#include <Mw/LowLevelMath.h>
/* Bitfield of cpu features we get from x86's CPUID */
#if defined(MwLLMathMMX)
#define FEATX86_MMX (1 << 23)
#define FEATX86_SSE (1 << 25)
#define FEATX86_SSE2 (1 << 26)
#endif
struct _MwLLMathVTable {
void (*Add)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Multiply)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Sub)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Reciprocal)(MwLLVec* a, MwLLVec* out);
void (*SquareRoot)(MwLLVec* a, MwLLVec* out);
void (*And)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Or)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*ShiftRight)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*ShiftLeft)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*Equal)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*GreaterThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*LesserThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
};
typedef struct _MwLLMathVTable MwLLMathVTable;
MwLLMathVTable** default_multi_table(void);
void mmx_apply(MwLLMathVTable**);
struct _MwLLMathVTable {
void (*add)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*multiply)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*sub)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*reciprocal)(MwLLVec* a, MwLLVec* out);
void (*squareRoot)(MwLLVec* a, MwLLVec* out);
void (*and)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*or)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*shiftRight)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*shiftLeft)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*equal)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*greaterThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
void (*lesserThen)(MwLLVec* a, MwLLVec* b, MwLLVec* out);
};
struct _MwLLVec {
void* buffer;
int ty;
MwU64 size;
MwLLMathVTable vtable;
};
void default_apply(MwLLVec*);
/* Bitfield of cpu features we get from x86's CPUID */
#if defined(MwLLMath_x86)
#define FEATX86_MMX (1 << 23)
// #define FEATX86_SSE (1 << 25)
#define FEATX86_SSE2 (1 << 26)
void mmx_apply(MwLLVec*);
#endif
#endif

View File

@@ -1,111 +1,129 @@
/* $Id$ */
#include <Mw/LowLevelMath.h>
#ifdef MwLLMathMMX
#ifdef MwLLMath_x86
#include "math_internal.h"
#include <mmintrin.h>
#define DO_MMX_INTRINSIC(intrin, _ty, _rty, _tyn) \
__m64 m = intrin(*(__m64*)&a->un._ty, *(__m64*)&b->un._ty); \
struct _tyn* t = (struct _tyn*)&m; \
out->un._rty = *t;
#define DO_MMX_INTRINSIC(intrin, _ty, _cty) \
int i = 0; \
for(; i < a->size; i += 8) { \
__m64 m = intrin(*(__m64*)&a->buffer[i], *(__m64*)&b->buffer[i]); \
memcpy(&((_cty*)out->buffer)[i], &m, sizeof(m)); \
}
static void mmx_add8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddb, u8, u8, _MwLLVecDataU8x8);
DO_MMX_INTRINSIC(_m_paddb, u8, MwU8)
}
static void mmx_sub8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubb, u8, u8, _MwLLVecDataU8x8);
DO_MMX_INTRINSIC(_m_psubb, u8, MwU8);
}
static void mmx_equal8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpeqb, u8, u8, _MwLLVecDataU8x8);
DO_MMX_INTRINSIC(_m_pcmpeqb, u8, MwU8);
}
static void mmx_add16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_paddw, u16, MwU16);
}
static void mmx_sub16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_psubw, u16, MwU16);
}
static void mmx_shiftRight16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psrlw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_psrlw, u16, MwU16);
}
static void mmx_shiftLeft16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psllw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_psllw, u16, MwU16);
}
static void mmx_equal16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpeqw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_pcmpeqw, u16, MwU16);
}
static void mmx_add32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddd, u32, u32, _MwLLVecDataU32x2);
DO_MMX_INTRINSIC(_m_paddd, u32, MwU32);
}
static void mmx_sub32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubd, u32, u32, _MwLLVecDataU32x2);
DO_MMX_INTRINSIC(_m_psubd, u32, MwU32);
}
static void mmx_shiftRight32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psrld, u32, u32, _MwLLVecDataU32x2);
DO_MMX_INTRINSIC(_m_psrld, u32, MwU32);
}
static void mmx_shiftLeft32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pslld, u32, u32, _MwLLVecDataU32x2);
DO_MMX_INTRINSIC(_m_pslld, u32, MwU32);
}
static void mmx_equal32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpeqw, u32, u32, _MwLLVecDataU32x2);
DO_MMX_INTRINSIC(_m_pcmpeqw, u32, MwU32);
}
static void mmx_addi8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddsb, u8, u8, _MwLLVecDataU8x8);
DO_MMX_INTRINSIC(_m_paddsb, i8, MwI8);
}
static void mmx_subi8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubsb, u8, u8, _MwLLVecDataU8x8);
DO_MMX_INTRINSIC(_m_psubsb, i8, MwI8);
}
static void mmx_addi16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_paddsw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_paddsw, i16, MwI16);
}
static void mmx_subi16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_psubsw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_psubsw, i16, MwI16);
}
static void mmx_greaterTheni8(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpgtb, u8, u8, _MwLLVecDataU8x8);
DO_MMX_INTRINSIC(_m_pcmpgtb, i8, MwI8);
}
static void mmx_greaterTheni16(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpgtw, u16, u16, _MwLLVecDataU16x4);
DO_MMX_INTRINSIC(_m_pcmpgtw, i16, MwI16);
}
static void mmx_greaterTheni32(MwLLVec* a, MwLLVec* b, MwLLVec* out) {
DO_MMX_INTRINSIC(_m_pcmpgtd, u32, u32, _MwLLVecDataU32x2);
DO_MMX_INTRINSIC(_m_pcmpgtd, i32, MwI16);
}
void mmx_apply(MwLLMathVTable** t) {
t[_MwLLVecTypeU8x8]->Add = mmx_add8;
t[_MwLLVecTypeU8x8]->Sub = mmx_sub8;
// t[_MwLLVecTypeU8x8]->GreaterThen = mmx_greaterThen8;
t[_MwLLVecTypeU8x8]->Equal = mmx_equal8;
t[_MwLLVecTypeU16x4]->Add = mmx_add16;
t[_MwLLVecTypeU16x4]->Sub = mmx_sub16;
t[_MwLLVecTypeU16x4]->ShiftLeft = mmx_shiftLeft16;
t[_MwLLVecTypeU16x4]->ShiftRight = mmx_shiftRight16;
// t[_MwLLVecTypeU16x4]->GreaterThen = mmx_greaterThen16;
t[_MwLLVecTypeU16x4]->Equal = mmx_equal16;
t[_MwLLVecTypeU32x2]->Add = mmx_add32;
t[_MwLLVecTypeU32x2]->Sub = mmx_sub32;
t[_MwLLVecTypeU32x2]->ShiftLeft = mmx_shiftLeft32;
t[_MwLLVecTypeU32x2]->ShiftRight = mmx_shiftRight32;
// t[_MwLLVecTypeU32x2]->GreaterThen = mmx_greaterThen32;
t[_MwLLVecTypeU32x2]->Equal = mmx_equal32;
t[_MwLLVecTypeU8x8]->Add = mmx_addi8;
t[_MwLLVecTypeU8x8]->Sub = mmx_subi8;
t[_MwLLVecTypeI8x8]->GreaterThen = mmx_greaterTheni8;
t[_MwLLVecTypeI8x8]->Equal = mmx_equal8;
t[_MwLLVecTypeU16x4]->Add = mmx_addi16;
t[_MwLLVecTypeU16x4]->Sub = mmx_subi16;
t[_MwLLVecTypeI16x4]->ShiftLeft = mmx_shiftLeft16;
t[_MwLLVecTypeI16x4]->ShiftRight = mmx_shiftRight16;
t[_MwLLVecTypeI16x4]->GreaterThen = mmx_greaterTheni16;
t[_MwLLVecTypeI16x4]->Equal = mmx_equal16;
t[_MwLLVecTypeI32x2]->Add = mmx_add32;
t[_MwLLVecTypeI32x2]->Sub = mmx_sub32;
t[_MwLLVecTypeI32x2]->ShiftLeft = mmx_shiftLeft32;
t[_MwLLVecTypeI32x2]->ShiftRight = mmx_shiftRight32;
t[_MwLLVecTypeI32x2]->GreaterThen = mmx_greaterTheni32;
t[_MwLLVecTypeI32x2]->Equal = mmx_equal32;
void mmx_apply(MwLLVec* vec) {
switch(vec->ty) {
case MwLLVecTypeU8:
vec->vtable.add = mmx_add8;
vec->vtable.sub = mmx_sub8;
vec->vtable.equal = mmx_equal8;
break;
case MwLLVecTypeU16:
vec->vtable.add = mmx_add16;
vec->vtable.sub = mmx_sub16;
vec->vtable.shiftLeft = mmx_shiftLeft16;
vec->vtable.shiftRight = mmx_shiftRight16;
vec->vtable.equal = mmx_equal16;
break;
case MwLLVecTypeU32:
vec->vtable.add = mmx_add32;
vec->vtable.sub = mmx_sub32;
vec->vtable.shiftLeft = mmx_shiftLeft32;
vec->vtable.shiftRight = mmx_shiftRight32;
vec->vtable.equal = mmx_equal32;
break;
case MwLLVecTypeU64:
break;
case MwLLVecTypeI8:
vec->vtable.add = mmx_addi8;
vec->vtable.sub = mmx_subi8;
vec->vtable.greaterThen = mmx_greaterTheni8;
vec->vtable.equal = mmx_equal8;
break;
case MwLLVecTypeI16:
vec->vtable.add = mmx_addi16;
vec->vtable.sub = mmx_subi16;
vec->vtable.shiftLeft = mmx_shiftLeft16;
vec->vtable.shiftRight = mmx_shiftRight16;
vec->vtable.greaterThen = mmx_greaterTheni16;
vec->vtable.equal = mmx_equal16;
break;
case MwLLVecTypeI32:
vec->vtable.add = mmx_add32;
vec->vtable.sub = mmx_sub32;
vec->vtable.shiftLeft = mmx_shiftLeft32;
vec->vtable.shiftRight = mmx_shiftRight32;
vec->vtable.greaterThen = mmx_greaterTheni32;
vec->vtable.equal = mmx_equal32;
break;
case MwLLVecTypeI64:
break;
case MwLLVecType_Max:
break;
}
}
#endif